After finding an article on the web that warned that writing your own floating-point output routine was a foolhardy enterprise ^{[2]} I decided to avoid the problem by getting **snprintf()** to write the float to a string buffer with:

snprintf(buffer, bufmax, "%g", f);

and then print the string in uLisp.

This worked nicely on the Arduino Due which I was using to test the code, although it added an overhead of over 10Kbytes to my code. However, I discovered that on most other platforms the floating-point support in **snprintf()** was disabled by default, so this wasn't going to be a solution I could use.

I therefore set out to write a floating-point output routine in C. The aim was that it should give the same output as **princ** in LispWorks Common Lisp, subject to differences in precision; my implementation has 32-bit short floats.

I prototyped the logic in Lisp before coding it in C. It's written in C-like Lisp to make it easy to translate into C once it's working.

After a few false starts I managed to get a reasonably compact version that seems to produce the correct output in all the test cases I've tried. I'd be interested if anyone can find a case that fails:

(defun pmantissa (f) (let* ((sig (floor (log f 10))) (mul (expt 10 (- 5 sig))) (i (round (* f mul))) d point) (when (= i 1000000) (setq i 100000) (incf sig)) (when (< sig 0) (princ "0.") (setq point t) (dotimes (j (1- (- sig))) (princ "0"))) (setq mul 100000) (dotimes (j 7) (setq d (truncate i mul)) (princ (code-char (+ (char-code #\0) d))) (setq i (- i (* d mul))) (when (zerop i) (unless point (princ ".0")) (return)) (when (and (= j sig) (>= sig 0)) (princ ".") (setf point t)) (setq mul (/ mul 10))))) (defun print-float (f) (let ((e 0)) (when (= f 0.0) (princ "0") (return-from print-float)) (when (< f 0) (princ "-") (setq f (- f))) ;; Calculate the exponent (when (or (< f 1e-3) (>= f 1e5)) (setq e (floor (log f 10))) (setq f (/ f (expt 10 e)))) (pmantissa f) ;; Print the exponent (when (/= e 0) (princ "e") (princ e))) (values))

Some examples:

CL-USER > (print-float 12345.6789) 12345.7 CL-USER > (print-float 123456.789) 1.23457e5 CL-USER > (print-float 0.00123456789) 0.00123457 CL-USER > (print-float 0.000123456789) 1.23457e-4 CL-USER > (print-float 0.99999999) 1.0

- ^ uLisp - Lisp for the Arduino, Micro Bit, and MSP430.
- ^ Printing Floating-Point Numbers on RyanJuckett.com.

My starting point was this routine on Rosetta Code ^{[2]}:

(defun fft (x) (if (<= (length x) 1) x (let* ((even (fft (loop for i from 0 below (length x) by 2 collect (nth i x)))) (odd (fft (loop for i from 1 below (length x) by 2 collect (nth i x)))) (aux (loop for k from 0 below (/ (length x) 2) collect (* (exp (/ (* (complex 0 -2) pi k ) (length x))) (nth k odd))))) (append (mapcar #'+ even aux) (mapcar #'- even aux)))))

The formatting of the original suggests it was written by a C programmer rather than a Lisp programmer, and I've tidied it up a bit above.

The test case is this simple waveform:

(fft '(1 1 1 1 0 0 0 0))

which gives:

CL-USER > (pprint (fft '(1 1 1 1 0 0 0 0))) (#C(4.0D0 -0.0D0) #C(1.0D0 -2.414213562373095D0) #C(0.0D0 0.0D0) #C(1.0D0 -0.4142135623730949D0) #C(0.0D0 0.0D0) #C(0.9999999999999999D0 0.4142135623730949D0) #C(0.0D0 0.0D0) #C(0.9999999999999997D0 2.414213562373095D0))

However, in searching for solutions to this problem I found an elegant version in Scheme using a purely functional style of programming with no variable assignments, by Prasenjit Saha ^{[3]}.

Inspired by his version here's a functional Common Lisp version that avoids variable assignments, or the use of the **loop** macro, and to my mind is much easier to understand:

(defun evens (f) (if (null f) nil (cons (car f) (evens (cddr f))))) (defun odds (f) (if (null f) nil (cons (cadr f) (odds (cddr f))))) (defun rotate (fun k l lis) (if (null lis) nil (cons (funcall fun k l (car lis)) (rotate fun (1+ k) l (cdr lis))))) (defun ph (k l j) (* (exp (/ (* (complex 0 -2) (* pi k)) l)) j)) (defun plusminus (a b) (append (mapcar #'+ a b) (mapcar #'- a b))) (defun fft2 (x) (if (= (length x) 1) x (plusminus (fft2 (evens x)) (rotate #'ph 0 (length x) (fft2 (odds x))))))

The routines **evens** and **odds** return lists containing every alternate element:

CL-USER > (evens '(0 1 2 3 4 5 6 7)) (0 2 4 6) CL-USER > (odds '(0 1 2 3 4 5 6 7)) (1 3 5 7)

The function **rotate** is a bit more complicated. It takes four parameters: The first is a function, the second and third are integers, and the fourth is a list. It applies the function to the first two parameters and each element of the list, with the first number incremented in successive calls. For example:

CL-USER > (rotate #'list 0 'x '(a b c d e)) ((0 X A) (1 X B) (2 X C) (3 X D) (4 X E))

The function **ph** performs the central calculation of the FFT, and **plusminus** takes two lists of equal length, and returns a single list of their pairwise sums followed by their pairwise differences:

CL-USER > (plusminus '(1 3 5) '(0 2 4)) (1 5 9 1 1 1)

Finally **fft2** recursively applies the Cooley–Tukey algorithm to calculate the FFT.

Result:

CL-USER > (pprint (fft2 '(1 1 1 1 0 0 0 0))) (#C(4.0D0 -0.0D0) #C(1.0D0 -2.414213562373095D0) #C(0.0D0 0.0D0) #C(1.0D0 -0.4142135623730949D0) #C(0.0D0 0.0D0) #C(0.9999999999999999D0 0.4142135623730949D0) #C(0.0D0 0.0D0) #C(0.9999999999999997D0 2.414213562373095D0))

- ^ uLisp - Lisp for the Arduino, Micro Bit, and MSP430.
- ^ Fast Fourier transform - Common Lisp on Rosetta Code.
- ^ A Fast Fourier Transform in Lisp on physik.uzh.ch.

Here's my attempt to come up with a short compelling example showing how object-oriented programming simplifies the writing of programs in Lisp:

Object-oriented programming allows you to organise programs in a more logical way. Instead of having a single program which operates on an inert mass of data, the data itself is told how to behave, and the program is implicit in the interactions of these new data “objects.”

For example, suppose we have two types of objects, rectangles and circles, and the functions **rectangle-p** and **circle-p** to test what type an object is.

Now suppose we want to write a program to find the areas of two-dimensional shapes.

The old non-object-oriented way to do this would be to write a single function which looked at the type of its argument and behaved accordingly. So, to find the area of an object x we would do:

(defun area (x) (cond ((rectangle-p x) (* (height x) (width x))) ((circle-p x) (* pi (expt (radius x) 2)))))

The object-oriented approach is to make each object able to calculate its own area. The **area** function is broken apart and a different version is provided for each type of object. These different versions of a function are called **methods**.

In Lisp methods are defined using **defmethod**, rather than **defun**. So the equivalent object-oriented definitions for **area** might be:

(defmethod area ((x rectangle)) (* (height x) (width x))) (defmethod area ((x circle)) (* pi (expt (radius x) 2)))

Like **defun**, in **defmethod** the function name is followed by a list of arguments, but any argument can be a list:

(argumenttype)

to specify that the function is only called if the argument is of that type.

When we call:

(area obj)

the correct method will automatically be chosen by CLOS according to what type of object **obj** is.

In object-oriented programming we define the type of each object using **classes**. In our simple example we have just two types of object, rectangles and circles. We could define these as follows:

(defclass rectangle ()) (defclass circle ())

The argument of **defclass** is the class that this class inherits from. In their most general form classes can form a hierarchy, like a tree, with the most general classes at the top and the more specialised classes further down. So we might make all the classes used by our program inherit from a **shape** class, and we might include **square** as a special case of **rectangle**:

(defclass shape ()) (defclass rectangle (shape)) (defclass circle (shape)) (defclass square (rectangle))

The **defclass** definition can also specify slots, which are variables associated with each instance of an object. For example, our rectangle objects could have a height and width, and our circle objects could have a radius:

(defclass rectangle (shape) (width height)) (defclass circle (shape) (radius))

Finally, when we want to make a new object we use **make-instance** to make an instance of the appropriate class, a bit like peeling a sheet off a pad of identical forms:

(setq myrect (make-instance 'rectangle :width 24 :height 10))

(Note that we would have to make the **defclass** definitions a bit more complicated for this to work as shown in practice).

Each instance of **rectangle** has its own separate **width** and **height** slots.

Now we can do:

> (area myrect)

and we'll get:

240

Why is the object-oriented approach better than the simple approach at the start of this section, using **defun** and a **cond** to check the different possible types of object?

- The object-oriented approach keeps the information about how to deal with each type of object in the method for that type of object, rather than having it in one large function that has to deal with all types of object.
- If at a later date you want to make your program handle a new type of object you simply have to add an appropriate class and methods, without needing to edit your existing methods.
- Slots are a convenient way of storing all the information about particular instances of a class.
- Because classes are hierarchical you can provide a single method that works on several classes in the hierarchy. For example, as defined above
**area**will automatically work on objects of type**square**because they are a subclass of**rectangle**.

Here's a full working example based on the methods and classes described above. You can run this in LispWorks to see how it works.

Suppose we are a manufacturer of perspex shapes for children.

First we define the classes. The perspex comes in different thicknesses, so we give the **shape** class a **thickness** slot:

(defclass shape () ((thickness :initarg :thickness :accessor thickness)))

This definition of the **thickness** slot has a few extra declarations:

- The
**:initarg**keyword says that we can initialise the slot to a value in**make-instance**with the**:thickness**keyword. - The
**:accessor**keyword says that we can access the slot with the function**thickness**.

Now we define the actual shapes, based on this **shape** class:

(defclass rectangle (shape) ((width :initarg :width :accessor width) (height :initarg :height :accessor height))) (defclass circle (shape) ((radius :initarg :radius :accessor radius)))

Because **rectangle** and **circle** are both based on **shape**, they each automatically inherit a **thickness** slot from **shape**.

Finally we define the methods:

(defmethod area ((x rectangle)) (* (height x) (width x))) (defmethod area ((x circle)) (* pi (expt (radius x) 2)))

The first method is specialised on **rectangle**; in other words, it only gets called if x is a **rectangle**. The second method is specialised on **circle**.

Now you can create an object as an instance of one of these classes:

(setq myshape (make-instance 'circle :radius 12 :thickness 2))

You can read its radius with:

(radius myshape)

or change its thickness with:

(setf (thickness myshape) 3)

and you can find its area with:

(area myshape)

Suppose we want to calculate the weight of one of our perspex shapes. We can define a method on **shape** which will work for all shapes that inherit from the **shape** class:

(defparameter *density* 2) (defmethod weight ((x shape)) (* (area x) (thickness x) *density*))

Now we can find the shape's weight with:

(weight myshape)

1. Define a class **triangle** with slots **base** and **height**.

Add an **area** method for **triangle** objects, and check it gives the correct weight for a triangle defined as follows:

(setq mytriangle (make-instance 'triangle :base 12 :height 6 :thickness 1))

2. Define **perimeter** methods for **rectangle** and **circle** objects that returns the length of each object's perimeter.