I'm endorsing what Bill suggested. If you are going to manage just one function the rest of it will be routine.
This might interest you: https://github.com/matlisp/matlisp Especially https://github.com/matlisp/matlisp/blob/t2/src/packages/quadpack/quadpack.lisp which seems to me quite easier to implement. Am 24.10.2015 um 16:28 schrieb Bill Page: > 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 <amc...@gmail.com> 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 <nil...@gmail.com> 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 <nil...@gmail.com> 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 >>>>> fricas-devel+unsubscr...@googlegroups.com. >>>>> To post to this group, send email to fricas-devel@googlegroups.com. >>>>> 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 >>> fricas-devel+unsubscr...@googlegroups.com. >>> To post to this group, send email to fricas-devel@googlegroups.com. >>> 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 fricas-devel+unsubscr...@googlegroups.com. >> To post to this group, send email to fricas-devel@googlegroups.com. >> 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 fricas-devel+unsubscr...@googlegroups.com. To post to this group, send email to fricas-devel@googlegroups.com. Visit this group at http://groups.google.com/group/fricas-devel. For more options, visit https://groups.google.com/d/optout.