Alasdair,

For entirely selfish reasons :) I would like to encourage you to
continue work on this since I also would like to be able use some of
the standard numeric libraries in FriCAS. But I am also sympathetic to
your reaction concerning the details in Lisp. One thing that might
help is that both FriCAS and OpenAxiom follow the original design of
Axiom which includes an intermediate language called BOOT.  BOOT was
intended to make Lisp-level programming easier for people who mostly
program in SPAD since the syntax is similar to SPAD without static
types. Some (most?) of what Kurt wrote in Lisp below and all of the
interface code that he did not include could be written in a
combination of BOOT and SPAD.

In any case I am motivated to try to help with this.

Cheers,
Bill Page

On 24 October 2015 at 04:28, Alasdair McAndrew <[email protected]> wrote:
>
> The more I read about Lisp the more difficult it seems.  It would probably be 
> just as easy for me to write a integrate.input file from scratch containing 
> the Gauss-Kronrod code, rather than wrestling with a language of which I have 
> little understanding, and no competence!
>
> On Sat, Oct 24, 2015 at 3:11 PM, Kurt Pagani <[email protected]> wrote:
>>
>>
>> I'm trying to explain it as good as I can (experts will correct me):
>>
>> I see three different methods:
>>
>> 1. start your Lisp REPL (pref. SBCL) and try to load QuickLisp, FriCAS:
>>
>> - (load "~/quicklisp/setup.lisp")
>> - (load "load-fricas.lisp")
>> - (ql:quickload ... whatever you want to via QuickLisp)
>> - (load "other_lisp_files_of_interest")
>> - (main)
>>
>> where "main" is a function which combines the various objects. You said
>> you were "a total Lisp newbie", then this method might not be the first
>> choice.
>>
>> 2. Instead of using a Lisp REPL one can use the one inside FriCAS,
>> however, except from loading "load-fricas.lisp" nothing changes with
>> respect to method 1, at least as long as you will stay within the Lisp
>> REPL.
>>
>> $ fricas -nosman
>>   )fin
>>   ...
>>   |spad| ; back to fricas
>>
>>
>> 3. Write a Lisp file containing all the "load" commands (except
>> "load-fricas.lisp" of course) and any packages and functions necessary
>> to "export" to the Fricas shell. Afterwards you have to write a SPAD
>> package which "imports" your Lisp functions (those you want to have in
>> FriCAS). I've found an example for QuickLisp (it's rather unfinished, so
>> I don't recommend to compile it): the SPAD section below is the file
>> "clx.spad" while in the second section below (after LISP) you can see
>> the file clx.lisp.
>>
>> Now compare for instance the function qlQuickLoad in clx.spad:
>>
>> --
>> qlQuickLoad : String -> SExpression
>> ++ qlQuickLoad is Lisp ql:quickload
>> ...
>> qlQuickLoad(s) == QL_-QUICKLOAD(s)$Lisp
>> --
>>
>>
>> with the function ql-quickload in clx.lisp:
>>
>> ;;; =================
>> ;;; QuickLisp section
>> ;;; =================
>>
>> (defun ql-quickload (s)
>>   (if (find-package "QUICKLISP")
>>   (ql:quickload s)
>>   (clx-error *pkg-err-ql*)))
>>
>> Now freely interpreted we have the following situation:
>>
>> If you call (in FriCAS) the functtion
>>
>>      (1)-> qlQuickLoad("myLib")
>>
>> then in the underground (Lisp) the expression
>>
>>      (ql-quickload "myLib") is evaluated.
>>
>> Note that Common-Lisp is case insensitive (unless you use |...|), so
>> that in SPAD the function "ql-quickload" should be written as
>> QL_-QUICKLOAD, where the underscore is necessary to escape the special
>> character "-".
>>
>> I admit it's confusing at times. But comparing corresponding functions
>> in the different sections you will get a feeling for it.
>>
>> In order to use "quadpack.lisp" within FriCAS you have just to do the
>> same as described above; choose the functions you want to see in FriCAS
>> and map them to the corresponding Lisp expressions in a SPAD package (or
>> domain). Of course, Maxima and FriCAS objects may be slightly different
>> internally, but in this case I think "quadpack" is quite generic since
>> it is a translation from Fortran (as you mentioned) and the
>> implementation should be pretty straighforward.
>>
>> A last remark: the Maxima function "quad_qag" for instance should be
>> named as "quadQag" (recommended but not mandatory ;)
>>
>>
>> Kurt
>>
>> **************************
>>
>> ----------
>> -- SPAD --
>> ----------
>>
>> $ cat clx.spad
>> )lisp (load "clx")
>> )abbrev package CLX clx
>> ++ Date Created: Sun Dec 21 03:29:45 CET 2014
>> ++ License: BSD (same as Axiom)
>> ++ Date Last Updated:
>> ++ Basic Operations:
>> ++ Related Domains:
>> ++ Also See:
>> ++ AMS Classifications:
>> ++ Keywords:
>> ++ Examples:
>> ++ References:
>> ++
>> ++ Description:
>> ++ CLX is a support package for Quicklisp, MathJax, tex2png and some
>> ++ other utilities.
>> ++
>> clx() : Exports == Implementation where
>>
>>
>>   Exports ==  with
>>
>>     %Exec : String -> SExpression
>>       ++ \spad{\%Exec} executes a command s in the shell
>>     %writeMathJax : String -> SExpression
>>       ++ \spad{\%writeMathJax} write TeX string to /tmp/mjax.html
>>     %displayMathJax : String -> SExpression
>>       ++ \spad{\%displayMathJax} write&display TeX string to /tmp/mjax.html
>>
>>     qlQuickLoad      : String -> SExpression
>>       ++ qlQuickLoad is Lisp ql:quickload
>>     qlUnInstall      : String -> SExpression
>>       ++ qlUnInstall is Lisp ql:uninstall
>>     qlSystemApropos  : String -> SExpression
>>       ++ qlSystemApropos  is Lisp ql:system-apropos
>>     qlUpdateAllDists : ()     -> SExpression
>>       ++ qlUpdateAllDists is Lisp ql:update-all-dists
>>     qlUpdateClient   : ()     -> SExpression
>>       ++ qlUpdateClient is Lisp ql:update-client
>>     qlWhoDependsOn   : String -> SExpression
>>       ++ qlWhoDependsOn is Lisp ql:who-depends-on
>>
>>
>>     mjax : Any -> SExpression
>>       ++ mjax display any expression (if possible) in the browser
>>
>>     evalToSlide  :  String -> SExpression
>>     evalToString :  String -> SExpression
>>
>>
>>   Implementation ==  add
>>
>>     %Exec(s) == CLX_-EXEC(s)$Lisp
>>     %writeMathJax(s) == CLX_-WRITE_-MATHJAX(s)$Lisp
>>     %displayMathJax(s) == CLX_-DISPLAY_-MATHJAX(s)$Lisp
>>
>>     qlQuickLoad(s)     == QL_-QUICKLOAD(s)$Lisp
>>     qlUnInstall(s)     == QL_-UNINSTALL(s)$Lisp
>>     qlSystemApropos(s) == QL_-SYSTEM_-APROPOS(s)$Lisp
>>     qlUpdateAllDists() == QL_-UPDATE_-ALL_-DISTS()$Lisp
>>     qlUpdateClient()   == QL_-UPDATE_-CLIENT()$Lisp
>>     qlWhoDependsOn(s)  == QL_-WHO_-DEPENDS_-ON(s)$Lisp
>>
>>     mjax(x:Any):SExpression ==
>>       t:String:=first tex(x::OutputForm::TexFormat)
>>       s:String:= concat ["$$", t::String, "$$"]
>>       CLX_-DISPLAY_-MATHJAX(s)$Lisp
>>
>>     --evalToString(s) == CLX_-EVAL_-TO_-STRING(s)$Lisp -- blocking ???
>>     --evalToSlide(s) == CLX_-EVAL_-TO_-SLIDE(s)$Lisp
>>       --r:String:=
>>       --split(r,char "@")
>>
>>
>> ;;;;;;;;;;;;
>> ;;; LISP ;;;
>> ;;;;;;;;;;;;
>>
>> $ cat clx.lisp
>> (in-package :boot)
>>
>> (defconstant *pkg-err-asdf* "ASDF package missing.")
>> (defconstant *pkg-err-ql*   "QuickLisp package missing.")
>>
>> (defun clx-error (s)
>>   "Print error message"
>>   (print s))
>>
>> (defun clx-exec (s)
>>   "Function: run-shell-command control-string &rest args [oboslete]"
>>   (if (find-package "ASDF")
>>         (asdf:run-shell-command s)
>>           (clx-error *pkg-err-asdf*)))
>>
>>
>> (defun clx-concstr (list)
>>   ;; concatenate a list of strings ; recall ~% = newline"
>>   (if (listp list)
>>       (with-output-to-string (s)
>>          (dolist (item list)
>>            (if (stringp item)
>>              (format s "~a~%" item))))))
>>
>>
>> (defun clx-getenv (name &optional default)
>>   "http://cl-cookbook.sourceforge.net/os.html; get env variables"
>>   ;; e.g. (clx-getenv "OS") => "Windows_NT"
>>   #+CMU
>>   (let ((x (assoc name ext:*environment-list* :test #'string=)))
>>     (if x (cdr x) default))
>>   #-CMU
>>   (or
>>     #+Allegro (sys:getenv name)
>>     #+CLISP (ext:getenv name)
>>     #+ECL (si:getenv name)
>>     #+SBCL (sb-unix::posix-getenv name)
>>     #+LISPWORKS (lispworks:environment-variable name)
>>     default))
>>
>>
>>
>> ;;; =================
>> ;;; QuickLisp section
>> ;;; =================
>>
>> (defun ql-quickload (s)
>>   (if (find-package "QUICKLISP")
>>         (ql:quickload s)
>>           (clx-error *pkg-err-ql*)))
>>
>> (defun ql-uninstall (s)
>>   (if (find-package "QUICKLISP")
>>         (ql:uninstall s)
>>           (clx-error *pkg-err-ql*)))
>>
>> (defun ql-system-apropos (s)
>>   (if (find-package "QUICKLISP")
>>         (ql:system-apropos s)
>>           (clx-error *pkg-err-ql*)))
>>
>> (defun ql-update-all-dists ()
>>   (if (find-package "QUICKLISP")
>>         (ql:update-all-dists)
>>           (clx-error *pkg-err-ql*)))
>>
>> (defun ql-update-client ()
>>   (if (find-package "QUICKLISP")
>>         (ql:update-client)
>>           (clx-error *pkg-err-ql*)))
>>
>> (defun ql-who-depends-on (s)
>>   (if (find-package "QUICKLISP")
>>         (ql:who-depends-on s)
>>           (clx-error *pkg-err-ql*)))
>>
>>
>> ;;; ===============
>> ;;; MathJax section
>> ;;; ===============
>>
>> (defconstant *url-show* "firefox -url file://C:/cygwin/tmp/~A")
>>
>> (defconstant *mjax-template* "<!DOCTYPE html>
>> <html>
>> <head>
>> <title>FriCAS Output</title>
>> <script type='text/x-mathjax-config'>
>>   MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
>> </script>
>> <script type='text/javascript'
>>
>> src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'>
>> </script>
>> </head>
>> <body>
>>  ~A
>> </body>
>> </html>")
>>
>> (defun clx-write-mathjax (s)
>>   (with-open-file (*standard-output* "/tmp/mjax.html"
>>      :direction :output
>>      :if-exists :supersede)
>>         (format t *mjax-template* s)))
>>
>>
>> (defun clx-display-mathjax (s)
>>     (progn (clx-write-mathjax s)
>>         (clx-exec (format nil *url-show* "mjax.html"))))
>>
>>
>> ;;; =============
>> ;;; LaTeX section
>> ;;; =============
>>
>> (defconstant *do-latex* "latex")
>>
>> (defconstant *beamer-template*
>> "\\documentclass[pdf]{beamer}
>> %\\usetheme{Warsaw}
>> \\usetheme{PaloAlto}
>> \\title[]{FriCAS}
>> \\subtitle[subttitle]{eval}
>> \\author[]{FriCAS}
>> \\institute[]{Cygwin}
>> \\date{\\today}
>> \\begin{document}
>> \\begin{frame}
>> \\titlepage
>> \\end{frame}
>> ~A
>> \\end{document}")
>>
>> (defconstant *frame-template* "\\begin{frame} $$~A$$ \\end{frame}")
>>
>> (defun clx-eval-to-string (s) (|parseAndEvalToString| s))
>> (defun clx-eval-to-latex  (s) (clx-eval-to-string (format nil "tex(~A)" s)))
>>
>> (defun clx-make-slide (s)
>>   (format nil *frame-template* (car (clx-eval-to-latex s))))
>>
>> (defun clx-write-slide (s)
>>   (with-open-file (*standard-output* "/tmp/slide.tex"
>>      :direction :output
>>      :if-exists :supersede)
>>         (format t *beamer-template* (clx-make-slide s))))
>>
>> (defun clx-display-slide (s)
>>     (progn (clx-write-slide s)
>>         (clx-exec (format nil *do-latex* "slide.tex"))))
>>
>>
>>
>>
>>
>>
>> Am 24.10.2015 um 03:13 schrieb Alasdair McAndrew:
>> > Just as an experiment I'm taking the quadpack.lisp file from the Maxima
>> > distribution, to see if I can install it and have it working under FriCAS.
>> > However, as a total Lisp newbie, I'm continuously stumped by trivial
>> > errors.  For example, quadpack.lisp uses the f2cl-lib package.  I can
>> > install this with quicklisp, but I don't know (yet) how to make that
>> > package available from within FriCAS.  For that matter, I don't know how to
>> > make the quicklisp package ql available: even the line
>> >
>> > (load "~/quicklisp/setup.lisp")
>> >
>> > which should work, doesn't appear to help - lines beginning with "(ql:  "
>> > are immediately flagged as errors and the ")read" compile is aborted.
>> >
>> > I'll keep on fiddling... (while Rome burns).
>> >
>> > -Alasdair
>> >
>> > On Sat, Oct 24, 2015 at 10:03 AM, Kurt Pagani <[email protected]> wrote:
>> >
>> >> Hello Alasdair
>> >>
>> >> What I have completely forgotten to mention in the last post:
>> >>
>> >> In the fricas/contrib folder there is a file load-fricas.lisp which
>> >> allows you to use FriCAS as a cl library itself. This way you can mix in
>> >> any kind of library as long there is no interference to the "boot"
>> >> package (I'm aware of only very few ones).
>> >>
>> >> BTW: I found that
>> >> (load "../lisp/primitives.lisp")
>> >> is missing in the file, so if you encounter problems it might be this
>> >> what caused an error. (see below). I used it occasionally in the
>> >> cl-jupyter frontend.
>> >>
>> >> --
>> >> Kurt
>> >>
>> >> #|
>> >> To use FriCAS as a Lisp library build FriCAS as usual and
>> >> keep the build tree.  Change path below to point to build
>> >> tree.  After that doing:
>> >>
>> >>  (load "load-fricas.lisp")
>> >>
>> >> will load and initialize FriCAS.
>> >>
>> >> Examples:
>> >> Using FriCAS command interpreter:
>> >>
>> >>  (in-package "BOOT")
>> >>  (|parseAndInterpret| "x^2")
>> >>
>> >>           2
>> >>    (2)  x
>> >>                                                     Type: Polynomial
>> >> Integer
>> >>  ((Polynomial (Integer)) WRAPPED 1 x (2 0 . 1))
>> >>
>> >> Directly calling math functions:
>> >>
>> >>  (defvar  *mult-i-sup*
>> >>      (|getFunctionFromDomain|
>> >>            '*
>> >>            '(|SparseUnivariatePolynomial| (|Integer|))
>> >>            '((|SparseUnivariatePolynomial| (|Integer|))
>> >>                (|SparseUnivariatePolynomial| (|Integer|)))))
>> >>  *MULT-I-SUP*
>> >>
>> >>  (SPADCALL '((2 . 1) (0 . 1)) '((5 . 1) (0 . 1)) *mult-i-sup*)
>> >>  ((7 . 1) (5 . 1) (2 . 1) (0 . 1))
>> >>
>> >>
>> >> Notes:
>> >> - all intersting functionality is in package called "BOOT".
>> >> - at mathematical level FriCAS is case-sensitive, so at Lisp level one
>> >>   has to use bars.
>> >> - the simplest interface is |parseAndInterpret| which takes a string
>> >>   as input and produces a Lisp form repesenting printed output.  As
>> >>   side effect |parseAndInterpret| prints the result.
>> >> - at deeper lever FriCAS functions are overloaded, so to call correct
>> >>   function one has to first use |getFunctionFromDomain| to get
>> >>   function which matches to given argument types.  Above I want to
>> >>   multiply two sparse univarate polynomials with integer coefficients.
>> >>   Since lookup may be expensive the caller is adviced to cache result
>> >>   of the lookup.
>> >> - FriCAS functions use special calling convention, so one has to use
>> >>   SPADCALL macro to call them.  Actually, |getFunctionFromDomain|
>> >>   returns a pair consistion of a function and an extra argument.
>> >>   SPADCALL takes care of decomposing the pair and appending the
>> >>   extra argument to the argument list.
>> >>
>> >> Currently FriCAS sets a few system (global) variables, for example
>> >> *read-default-float-format* is set to 'double-float -- in principle
>> >> FriCAS settings may interfere with other programs.
>> >>
>> >> |#
>> >> (let ((*default-pathname-defaults*
>> >>        #P"~/Development/ax-build/src/interp/"))
>> >>      (load "../lisp/fricas-package.lisp")
>> >>      (load "../lisp/fricas-config.lisp")
>> >>      (load "../lisp/fricas-lisp")
>> >>      (load "../lisp/primitives.lisp") ;;;+kfp
>> >>      (load "makeint.lisp"))
>> >> (in-package "BOOT")
>> >> (fricas-init)
>> >>
>> >> (in-package "BOOT")
>> >>  (|parseAndInterpret| "x^2")
>> >> kfp@helix:~/Development/fricas/contrib$
>> >>
>> >>
>> >> Am 23.10.2015 um 09:24 schrieb Waldek Hebisch:
>> >>> Alasdair McAndrew wrote:
>> >>>>
>> >>>> I was looking at some lisp numeric libraries: gsll at
>> >>>> https://common-lisp.net/project/gsll/ (which is a wrapper for the Gnu
>> >>>> Scientific Library GSL), as well as mjrcalc at
>> >>>> http://www.mitchr.me/SS/mjrcalc/.  I imagined that as these were Lisp
>> >>>> libraries, there would be some way of integrating them into FriCAS - or
>> >> at
>> >>>> least making them available so that they can be used from within a
>> >> FriCAS
>> >>>> session.  However, my attempts (such as they were) came to nothing: and
>> >> I
>> >>>> wasn't sure whether to )compile, )read, or do something else.
>> >>>>
>> >>>> Is there some documented standard method of integrating external
>> >> libraries
>> >>>> with FriCAS?
>> >>>
>> >>> Concerning documentation, I wrote some time ago about interfacing
>> >>> to one of Lapack function.
>> >>>
>> >>> Lisp functions are a bit easier than other languages, but not
>> >>> much.  To use a library from FriCAS, one need to first decide
>> >>> in interface.  That is how FriCAS types correspond to library
>> >>> types.  Normally this involves writing FriCAS domain/package
>> >>> with apropritate declarations.  One example may be plotting
>> >>> subsystem:  at Spad level there are viewport domains which
>> >>> export somewhat high-level interface and implement operations
>> >>> calling low-level functions.  The low-level parts are done
>> >>> by several Lisp functions which are called using '$Lisp'
>> >>> qualification.  The interface uses several constans defined
>> >>> as Spad macros -- the constants on Spad side must agree
>> >>> with constants used at other side (that is in C code).
>> >>>
>> >>> At lower level one needs to ensure that the code is available.
>> >>> Standard FriCAS code is either already loaded or FriCAS knows
>> >>> how to load it on demand.  With arbitrary Lisp code one
>> >>> can use ')read' (which compiles files and then loads it).
>> >>> I am affraid we do not have a special command to load
>> >>> Lisp without compiling, be one can do this via ')lisp'
>> >>> command like:
>> >>>
>> >>> )lisp (load "prog.fasl")
>> >>>
>> >>> Note that FriCAS may run only using AXIOMsys executable,
>> >>> which contains Lisp compiler but may miss large part
>> >>> of Lisp environment.  For example, you had problem
>> >>> because Lisp compiler inside FriCAS did not know
>> >>> where to find Lisp libraries bundled with sbcl.
>> >>>
>> >>> Currently for non-Lisp libraries one have to create
>> >>> apropriate wrappers at Lisp level -- basically specify
>> >>> type of C routine so that Lisp knowns how to pass
>> >>> arguments.  In sbcl non-Lisp dynamic libraries are
>> >>> easy to use: to load them one needs to use
>> >>> '|quiet_load_alien|' routine giving it path to the
>> >>> library.  After loadnig wrappers become usable.
>> >>> When it comes to Lisp libraries each Lisp is
>> >>> slightly different.  In sbcl one can load Lisp
>> >>> code (which either looses execution time if
>> >>> file is interpreted or looses time compiling it),
>> >>> load a fasl (which contains already compiled code
>> >>> but still needs nontrivial time to load) or create
>> >>> a new image.  Images start fast, but they take
>> >>> some effect to create, in particular one needs
>> >>> to make sure that they are properly initialised.
>> >>> Also. each image contains a copy of AXIOMsys
>> >>> executable so multiple images could take
>> >>> a lot of space.  Concerning fasl-s, there
>> >>> are some provisions to create aggregate fasl-s
>> >>> but usually each file gives a sparate fasl,
>> >>> so in case of multifile library one have to
>> >>> load several files.
>> >>>
>> >>> There is extra difficulty with using Lisp libraries:
>> >>> modern Lisp code frequently uses so called keyword
>> >>> arguments.  In FriCAS using keyword arguments is
>> >>> awkward, so one may be forced to create wrappers
>> >>> at Lisp level which present interface free of
>> >>> keyword arguments.
>> >>>
>> >>> To summarize, if you have Lisp library in a single
>> >>> file that uses FriCAS compatible data representation,
>> >>> than use may be as easy as
>> >>>
>> >>> )read "file.lisp"
>> >>>
>> >>> DO_SOMETHING(42)$Lisp
>> >>>
>> >>> But interesting things may require extra interface code.
>> >>>
>> >>> BTW: Are there some specific routines that you need or
>> >>> do want just to have the libraries handy?
>> >>>
>> >>
>> >> --
>> >> You received this message because you are subscribed to a topic in the
>> >> Google Groups "FriCAS - computer algebra system" group.
>> >> To unsubscribe from this topic, visit
>> >> https://groups.google.com/d/topic/fricas-devel/q18Av7P3jnM/unsubscribe.
>> >> To unsubscribe from this group and all its topics, send an email to
>> >> [email protected].
>> >> To post to this group, send email to [email protected].
>> >> Visit this group at http://groups.google.com/group/fricas-devel.
>> >> For more options, visit https://groups.google.com/d/optout.
>> >>
>> >
>> >
>> >
>>
>> --
>> You received this message because you are subscribed to a topic in the 
>> Google Groups "FriCAS - computer algebra system" group.
>> To unsubscribe from this topic, visit 
>> https://groups.google.com/d/topic/fricas-devel/q18Av7P3jnM/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to 
>> [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/fricas-devel.
>> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
> --
>
> --
> You received this message because you are subscribed to the Google Groups 
> "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/fricas-devel.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/fricas-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to