Jump to my Home Page Send me a message Check out stuff on GitHub Check out my photography on Instagram Check out my profile on LinkedIn Check out my profile on reddit Check me out on Facebook

Mitch Richling: MJRCALC – LISP Mathematical Library

Author: Mitch Richling
Updated: 2022-06-26

Table of Contents

1. What is it?

I have developed a great affinity for using LISP as an interactive mathematical problem solving tool and general algorithm development environment. This has resulted in the accumulation of a good deal of mathematically oriented LISP code over the years, and sharing that code is what this page is all about. So, if you are a mathematically inclined LISPer looking for a particular mathematical routine, then you may well be in the right place – assuming you have a high tolerance for ugly/buggy LISP and can forgive my unapologetic, raging case of NIH Syndrome!

2. How do I use it?

First and foremost, I keep a REPL up and running all the time with this code loaded – makes for a great alternative to those silly GUI calculator applications! Please note the code really is designed for interactive use inside of a smart REPL. I use SLIME+SBCL inside of GNU Emacs. *MJRCALC* is in no way a replacement for tools like Maple or Mathematica – I use them both. Instead of trying to do everything with a single, powerful tool, I find my problem solving efficiency is much higher when I use a suite of specialized tools for tasks each is particularly good at, and this is where *MJRCALC* comes into play. I think of it as a bit of glue allowing me to more effectively weave such tools together. In fact, I frequently have several mathematical tools running in the same Emacs session with *MJRCALC*: Octavestats Maximastats GAPstats Macaulay2stats and R Speaking of weaving systems together, *MJRCALC* can drive GNUPlot through a pipe for simple, immediate visualization. For more sophisticated, interactive visualization, *MJRCALC* can produce VTK files for tools like VisIt and Paraview – I really love VisIT. For less immediate visualization needs, *MJRCALC* can also generate files for POV-Ray.

What can all of this LISP code do? That's a hard question to answer directly, so I'll just list some of the things I have used it for over the years:

  • Desktop calculator replacement. ;)
  • Development and prototyping of deeply algorithmic and/or mathematical software
  • Numerical analysis
    • linear algebra
    • integration
    • ODEs
    • PDEs
    • Optimization
    • Root finding
  • Dynamical systems modeling and simulation (ODEs, PDEs, and algebraic equations)
    • Efficient solutions to Kepler's equation
    • High speed orbital dynamics (modeling the motion of thousands of solar system bodies)
    • High accuracy integration of planetary systems
    • Large scale particle simulation (Galactic dynamics, fungal growth, fountains, …)
    • Diffusion simulations
    • Mathematical Population dynamics
  • Symbolic algebra
    • Computational commutative algebra (solving polynomial systems, Grobner basis, etc…)
    • Non-numeric root localization
    • Rational and integer roots and critical points
    • Combined symbolic and numerical algorithms
    • Factorization of polynomials over the integers and prime order fields
    • Symbolic differentiation of LISP forms
    • Analytical solution of differential equations
  • Combinatorial enumeration and counting algorithms
    • Most of the 12-fold way
    • Several combinatorial functions
    • Generation of combinatorial objects (sets, cross products, permutations, combinations)
  • Computational group theory
    • Electron orbital mechanics
    • Crystal lattice formation
  • Probabilistic modeling and simulation (complex systems or statistical tests)
  • Sophisticated data visualization problems
  • Project Euler problems

4. Support

Please feel free to contact me if you find a bug, have an idea for an improvement, or just want to chat about implementation details. I can't guarantee I'll be able to act on such feedback in a timely fashion, but I do try very hard to eventually read and respond to all of my mail.

4.1. Paid support

Sorry, I don't provide paid support for this product. I have previously accepted contracts for very specific enhancement requests; however, my acceptance has been most strongly influenced by just how interesting the project was and not the cash offer.

4.2. Contributed Patches

I hate to say it, but contributed patches are difficult to deal with because of the complexity of copyright and IP law. I would rather get a bug report or enhancement request in plain English than a patch file.

4.3. About Quality and Consistency

This code base is an organically growing and evolving project dynamically changing as my work and needs evolve. This has a couple implications. First, this code base will always contain various functions in the middle of being re-factored (i.e. broken) or in the process of being implemented. The second implication is that I freely change things as I recognize dumb API decisions and find opportunities to make the code work better. If you plan on including this code in a long term project, then my advice is to fork the code and then be very careful about updates.

5. Loading and using the Code in your REPL

The authoritative source for information regarding how to load the code into your LISP is found in the documentation string for the function MJR_META_HELP found in the :MJR_META package in the file lib-meta.lisp. What follows is a brief, perhaps out of date, account of what you can find documented that file.

lib-meta.lisp.

5.1. The ASDF Way

If your LISP has a modern (post v3) version of ASDF installed and you have placed the source for *MJRCALC* into one of the places your ASDF looks for packages, then you can simply do the following:

(load "/full/path/to/where/you/put/*MJRCALC*/sup-lm-asdf.lisp")

Of course you can use the file name, not the full path, if your LISP is in the directory with the *MJRCALC* source. The code in the sup-lm-asdf.lisp file is quite simple. In essence, it runs three functions:

(require :asdf)
(asdf:load-system :mjrcalc)
(mjr_meta::mjr_meta_use-packages :BASE-PATH "/full/path/to/where/you/put/*MJRCALC*/")

5.2. The Meta Way

While most users will make use of ASDF, this not a requirement. The :MJR_META package can load the code (and do a whole lot more). If you just want to load everything up and do a use-package on everything, then the following will do the trick:

(load "/full/path/to/where/you/put/*MJRCALC*/lib-meta.lisp")
(mjr_meta::mjr_meta_load-packages :BASE-PATH "/full/path/to/where/you/put/*MJRCALC*/")
(mjr_meta::mjr_meta_use-packages :BASE-PATH "/full/path/to/where/you/put/*MJRCALC*/")

If your LISP is in the directory with the *MJRCALC* code, then you can nix the :base-path argument, and use just the file name in the load call. In fact, if you are in the directory with the *MJRCALC*, then you could simply load up sup-lm-meta.lisp.

(load "sup-lm-meta.lisp")

This last method is most like the load system used by *MJRCALC* before the conversion to ASDF. So if you have some old code looking for an equivalent to the historical load method, this is where to start.

5.3. The Hard Way

If you want to load the stuff up yourself then you will need to be careful of code dependencies. In the following graph the prefix of "MJR_" has been removed. Normal code is blue, and test code is pink. The arrows point in the direction of the dependency

grntZ.png

6. Interactive Use

All the functions are contained in packages. All package names begin with the string "MJR_". Following this standard prefix is a tag describing the category of functionality and an underscore. Immediately after this second underscore, is a descriptive name for the function. For example, "MJR_MAT_NORM" is a matrix function computing a norm while "mjr_nleq_root-newton" is a function for "NonLinear EQuations" which finds roots via Newton's method.

Because of this naming structure, tab completion may be used to great advantage both as a way to save typing effort and a way to discover function names. SLIME shows the function argument names in the Emacs message window after the function name and a space are typed at the REPL prompt, so function arguments are somewhat systematically named across packages and are a bit more verbosely named than is usual for LISP code.

All the functions have a comment string, so you can use LISP's documentation system to learn about them. Most packages have a "help" function, mjr_nleq_help for example, which will dump its own documentation string when evaluated – this string generally contains a description of the package and some information useful for understanding how to use the package. You can also take a look at the comment at the top of each file. The unit tests, linked in the download section below, can be a great help in understanding what the functions are intended to do. Finally, several examples linked below may be helpful in understanding how to use the library.

7. Code Base

The source is on github.

exp-BoatGo.lisp
Drug smuggler boat path
exp-ClassicOptAckley.lisp
Analysis of the classic Rosenbrock banana optimization test function.
exp-ClassicOptBanana.lisp
Analysis of the classic Rosenbrock banana optimization test function.
exp-ClassicOptBeale.lisp
Analysis of the classic Beale optimization test function.
exp-ClassicOptFreudensteinRoth.lisp
Analysis of the classic Freudenstein-Roth optimization test function.
exp-CLT.lisp
Theoretical family of probability distributions of sums of an input PDF represented as a historgram.
exp-compareComplexFunction.lisp
Compare the value of a function in Maxima vs on in MJRCALC.
exp-ComplexFunctionViz.lisp
Complex function visualization via VTK files.
exp-dXXXX.lisp
Example for :MJR_DQUAD.
exp-Euler.lisp
Solutions to Project Euler Problems.
exp-FixedPointItr.lisp
Some :MJR_NLEQ examples.
exp-Gravity2D.lisp
Demonstrate the danger of assuming everything is a sphere in gravity problems.
exp-Gravity3D.lisp
Difference between two gravitational systems with the same total mass.
exp-IntFactors.lisp
For the integers n in [1,72], list the first integer such that it has n unique divisors.
exp-IntrpMitch.lisp
Error Interpolating Runge's Function with Mitch Nodes of the First Kind vs Chebyshev Nodes.
exp-IntrpRunge.lisp
Demonstrate how adding more interpolation poitns may lead to worse fit.
exp-Kepler.lisp
Draw Newton-like fractal and output to a TGA file.
exp-Life.lisp
Read in a life RLE file, and iterate (dumping a TGA at each step) until the pattern cycles.
exp-MandelbrotOrbit.lisp
Compute Mandelbrot set, and dump it to a TGA file using unique coloring scheme.
exp-MandelbrotPot.lisp
Draw the potential of the mandelbrot set.
exp-MandelbrotTGA.lisp
Compute Mandelbrot set, and dump it to a TGA file using a nice pallet.
exp-MandelbrotVTK.lisp
Draw the Mandelbrot set, and save it as a VTK file.
exp-marsden-ch3sec3ex17.lisp
Solving a vector calculus problem.
exp-Newton.lisp
Draw Newton fractal and output to a TGA file.
exp-Newton2.lisp
Modified Newton's method fractals colored with the arg of the 20'th iterate.
exp-ODEalgCmp.lisp
Solve a simple ODE, and plot the results.
exp-ODEcannon.lisp
Cannon shot simulation.
exp-ODEcircle.lisp
Example of an ODE plot.
exp-ODElorenzDEQ.lisp
Compute (with :MJR_ODE) and draw the Lorenz strange attracter.
exp-ODElorenzEuler.lisp
Compute and draw the Lorenz strange attracter without :MJR_ODE..
exp-ODEpopulationCompete.lisp
Plot the direction field for an ODE of two competing populations.
exp-ODErossler.lisp
Compute the Rossler strange attracter.
exp-ODEthreeBody.lisp
A famous 3-body problem.
exp-OrthoPolys.lisp
Draw several sets of orthogonal polynomials.
exp-PiPrime.lisp
Find primes who's quotient approximates pi. We want the smallest primes for any given accuracy.
exp-PiRandom.lisp
Approximate pi with random numbrs.
exp-PolyLegendreRoots.lisp
Compute the nodes for Gauss-Legendre integration with high accuracy.
exp-PovGraphs.lisp
Some graphs with Povray – using general p.pov-like code.
exp-PovMixRes.lisp
How to draw a surface with a grid at one scale, and lines at another.
exp-PovWaveGraph.lisp
Generate a height field TGA and image map TGA file for a PovRay render.
exp-PrimePairs.lisp
Find composite numbers which are the product of two primes that are a distance of d apart where d in [1, 150].
exp-PrimePi.lisp
The prime counting function (pi) and a pair of bounding functions.
exp-ProbNeedle.lisp
Buffon's Needle Problem.
exp-pursuit.lisp
Drug smuggler boat path
exp-qmci.lisp
Benchmark and demonstrate basic mjr_qmci functionality.
exp-ratTrig.lisp
exp-sierpinski.lisp
Draw a colorful Sierpinski gasket-like thingy, and output the drawing as an SVG file
exp-svgCircles.lisp
Generate some SVGs with mathematical art using thousands of circles.
exp-svgDemo.lisp
Demo of the SVG package.@EOF
exp-SwirlyGraph.lisp
Draw a nice and swirly image.
exp-VTKcolorSpace.lisp
Draw the RGB Cube and HSL sphere.
pre-qmci.lisp
Quasi-Monte Carlo Integration.
lib-gfp.lisp
Interactive GF(p) library – modular arithmatic.
lib-gpoly.lisp
Generate Polynomial Code For General Fields.
lib-meta.lisp
Meta package for working with MJRCALC packages.
lib-sia.lisp
Simple Interval Arithmetic (with guess).
use-a.lisp
Angle (and time-ish) utilities.
use-annot.lisp
Provide data annotation tools – DSIMP and DQUAD.
use-arr.lisp
Array utilities.
use-cas.lisp
Very basic computer algebra on :MJR_MXP objects.
use-char.lisp
Character (ASCII & EBCIDIC) tools.@EOL
use-chem.lisp
Chemical element data.
use-chk.lisp
Floating point comparison: disaster prevention.
use-cmp.lisp
Floating point comparison: best guess.
use-color.lisp
Color theory (color space conversions and computations).
use-colorize.lisp
Interface for :MJR_COLORIZED and :MJR_COLORIZER.
use-colorized.lisp
Colorization of discrete spaces (Z_n).
use-colorizer.lisp
Colorization of continuous spaces (R, C, R^2, R^3, C, I, I^2, and I^3).
use-combc.lisp
Constructive Combinatorics: Generating combinatorial objects.
use-combe.lisp
Enumerative Combinatorics: Counting combinatorial objects.
use-const.lisp
Physical constants – with units.
use-date.lisp
Handy date stuff.
use-dft.lisp
DFT and inverse DFT.
use-dquad.lisp
Data sets on QUADrilateral (rectilinear) grids.
use-dsimp.lisp
Data sets on SIMPlicial complexes.
use-ee.lisp
Electronics Engineering.
use-eps.lisp
Floating point comparison: within EPSilon.
use-fsamp.lisp
Sample mathematical functions and create DQUADs and DSIMPs.
use-geo.lisp
Geographic and cartographic computations.
use-geom.lisp
Computational Geometry.
use-gnupl.lisp
Plotting dquads with GNUPlot.
use-ia.lisp
User interface wrapper for :MJR_SIA.
use-intg.lisp
Numerical integration of univariate real functions.
use-intrp.lisp
Polynomial interpolation.
use-intu.lisp
Handy integer utilities.
use-mat.lisp
Matrix math library.
use-matt.lisp
Generate and compute with various test matrices.
use-mxp.lisp
Mathematical eXPressions library.
use-ndiff.lisp
Numerical differentiation.
use-nleq.lisp
Non-linear equation root finding.
use-nleqm.lisp
Multiple Non-linear EQuation root location.
use-numu.lisp
Numerical utilities.
use-ode.lisp
ODE (Ordinary Differential Equation) IVP (Initial Value Problem) solvers.
use-opt.lisp
Univariate function optimization.
use-optm.lisp
Multivariate function OPTimization.
use-perm.lisp
Permutation group computation.
use-poly.lisp
Polynomials over complex, real, rational, and integers.
use-polygfp.lisp
Univariate polynomials over prime order fields – i.e. GF(p)[x].
use-pov.lisp
Produce Povray files!
use-prime.lisp
Computational Number Theory.
use-prng.lisp
Uniform random deviate generators.
use-prob.lisp
Augments and supports :mjr_probau.
use-probau.lisp
Balls And Urns probability distributions.
use-probe.lisp
Empirical probability distriubtions.
use-probu.lisp
Computations on PDFs (Probability Distribution Functions).
use-pwf.lisp
piecewise function stuff.
use-rtrig.lisp
Rational Approximations For Irrational Functions.
use-stats.lisp
Statistics: Averages, histograms, sub-samples, simple linear regression.
use-string.lisp
String utilities.
use-svg.lisp
Simple API to create SVG files
use-tga.lisp
Raster image stuff.
use-units.lisp
Unit conversion tool.
use-util.lisp
Utilities.
use-vec.lisp
Mathematical vectors.
use-vtk.lisp
Write VTK files.
use-vvec.lisp
Virtual vectors.

8. FAQ

I went without a FAQ for *MJRCALC* for a long time. Now that the user community has grown, it seems the time has come to start one up.

Do you really use this as your desktop calculator?
Yes. LISP has great numeric support (one of the best numeric type hierarchies ever developed in any language). I'm an old RPN guy, so prefix notation is very comfortable for me; however, I occasionally use the :MJR_MXP package to enter an expression using infix notation.
You have implemented several algorithms in *MJRCALC* for which better, or standard, implementations already exist. Why?
Any number of reasons.
  • I may have been reading about an algorithm new to me, and wanted to try and implement it. The :MJR_DEQ package is a good example – the whole thing was written simply because I was reading some really good books on the numerical solution of differential equations!
  • I may have needed some kind of odd functionality not found in the standard algorithms. The :MJR_MAT package is a good example of this – you don't find many matrix elimination routines capable of using Givens, Householder, and Gauss steps on the same matrix!
  • It could have just been my raging case of NIH Syndrome I mentioned near the top of this page. ;)
Could you integrate *MJRCALC* with MY-FAVORITE-PACKAGE?
I have a rule about strong coupling and dependencies on external code. I don't do it. This is mostly because of the level of effort required to keep up with external libraries – I want *MJRCALC* to work any place I take it. I don't want to worry about trying to set up some complex environment just to get the code to run. On the other hand, loose coupling is very much a possibility. For example, the :MJR_PRNG allows one to plug in external libraries like the most excellent mt19937 package available via Quicklisp.
Some of the numerical methods are strangely general or non-standard (even at the cost of speed)?
This is very true. It is a feature!! One of the reasons I wrote this library was to provide a test bed for developing new algorithms in numerical analysis – not just to implement well known algorithms. For example, the :MJR_DEQ library uses plugins for the step methods allowing one to easily test new RK methods. Another example is some of the generic code in :MJR_MAT allowing matrix elimination using a mix of Givens, Householder, and Gauss steps. When I need a standard solver and I care about performance or size, then I generally use one of the many high quality libraries available (NetLib is your friend!)
Can I use *MJRCALC* in a commercial product?
Sure so long as you follow the license agreement That said, you should be careful. I don't manage *MJRCALC* like a commercial product with regard to backward compatibility. Note also I generally do not provide any form of commercial support. I have some advice about this in the section above about support
How is *MJRCALC* licensed?
I use a BSD-like license. You can find it in the licence file file in the distribution.