Arithmetic Operations

Mathematical Operations And Comparisons Using PicoLisp . 
Drakopoulos Anastasios
anasdrak@gmail.com

Summary. This article describes mathematical operations and comparisons using PicoLisp.

Introduction.
PicoLisp, as well as every Lisp dialect, promotes prefix notation. This fact means that one should write first of all the arithmetic operator and afterwards the numbers on which it will operate. For example :
(+ 1 2) → 3
(+ 1 2 3) → 6
Generally speaking, you have to provide a list to the interpreter (read – eval -print loop). The first member of this list has to be a function. The rest of the list are the arguments which will be used by the function. That's why we use “car” and “cdr” all the time. The first returns the first member of the list which is the function to be applied on the rest of the list and the second returns the rest of the list which includes the arguments of the function. The general case follows:
(function-name argument-sublist)

Addition.
The symbol for addition is “+” which can accept more than two arguments. In this case one could add infinitely many numbers using only one “+” symbol. You start understanding why prefix notation becomes an advantage.
(+ 1 2 3 4) → 10
A point to be considered before any decimal computation is the value of “*Scl1”. This value holds the current fixpoint input scale. Its initial value is zero. In this case you cannot add decimal numbers and you get integer addition only. For example :
: (+ 1.2 3.0) -> 4
: (+ 1.2 3.1) -> 4
if you want to use fixnums then you should adjust the precision of the decimal part using the global variable “*Scl”. In case you want three decimal digits you write:
(setq2 *Scl 3)
or
(scl 3)
Repeating the previous calculations you take:
: (+ 1.2 3.0) -> 4200
 : (+ 1.2 3.1)  -> 4300
If you don't feel nice with the results try “format3” to see the expected values on the screen :
: (format (+ 1.2 3.0) *Scl) -> "4.200"
: (format (+ 1.2 3.1) *Scl) -> "4.300"
Even if you don't see the formatted output the machine computes the right results. Consider the following example:
: (setq a1 2.22) -> 2220
: (setq a2 3.11) -> 3110
        : (setq a3 (+ a1 a2)) -> 5330
            : (format a3 *Scl)   -> "5.330"

Subtraction.
The symbol for subtraction is “-” which can accept more than two arguments. In this case one could subtract  infinitely many numbers using only one “-” symbol. Consider the following examples:
: (- 5 1 2)  -> 2
     : (- 5.0 1.1 2.01)  -> 1890
        : (format (- 5.0 1.1 2.01) *Scl) -> "1.890"

Multiplication.
The symbol for multiplication is “*” which can accept more than two arguments. In this case one could multiply  infinitely many numbers using only one “*” symbol. Consider the following examples:
: (* 2 3 4)  ->  24
In order to multiply fixnums we use the operator “*/” as described in the following example:
: (format (*/ 12.0 9.0 1.0) *Scl)  -> "108.000”
The operator “*/” when first in a list , multiplies the first two arguments and divides the result of multiplication with the third argument.

Division.
The symbol for division is “/” which can accept more than two arguments. In this case one could divide  infinitely many numbers using only one “/” symbol. Consider the following examples:
: (/ 4 2)    -> 2
: (/ 12 2 3) -> 2
In order to divide fixnums we use the operator “*/” as described in the following example:
: (format (*/ 12.0 1.0 9.0) *Scl)    -> "1.333"
The operator “*/” when first in a list , multiplies the first two arguments and divides the result of multiplication with the third argument.

Functions For Easier Arithmetic Operations.
In order to facilitate the arithmetic operations with fixnums we can define the following functions for addition, subtraction, multiplication and division respectively. Each of them accepts indefinite number of arguments and checks if the scale for fixnums is defined. If the scale is defined then proceeds to the operation. Otherwise asks the user to define the scale and call the function again.

(de A+ @  (if (<> *Scl 0)
(pass +)
(prog (println "Key in : (setq *Scl 6) and try again.") NIL )))

(de A- @ (if (<> *Scl 0)
(pass -)
(prog (println "Key in : (setq *Scl 6) and try again.") NIL )))

(de A* @ (if (<> *Scl 0)
(*/ (arg 1) (arg 2) 1.0)
(prog (println "Key in : (setq *Scl 6) and try again.") NIL )))

(de A/ @ (if (<> *Scl 0)
(/ (* (arg 1) 1.0)  (arg 2))
(prog (println "Key in : (setq *Scl 6) and try again.") NIL )))

It is obvious that the format is not acceptable by humans and for this reason we define the following functions which are used in order to have the right string printed on the screen. Keep in mind that the previous functions A+,A-,A*,A/ return numbers that can be used for further arithmetic operations while the following functions S+,S-,S*,S/ return strings which cannot be used for further operations except for a nice printing on the screen.

(de S+ @ (format (pass A+) *Scl))
(de S- @ (format (pass A-) *Scl))
(de S* @ (format (pass A*) *Scl))
(de S/ @ (format (pass A/) *Scl))

Examples of calling these functions follow:
: (A+ 1.2 2.32) -> 3520
: (A- 3.9 1.2) -> 2700
: (A* 1.2 2.0) -> 2400000
: (A/ 12.0 1.7) -> 7058823
: (S+ 1.2 2.32) -> "3.520"
: (S- 3.9 1.2) -> "2.700"
: (S* 1.2 2.0) -> "2.400"
: (S/ 12.0 1.7) -> "7.058"

Power of number.
The symbol for the computation of power of number is “**”. Consider the following examples:
: (** 2 3)    -> 8

Square Root.
sqrt → Returns the square root. If you want decimal digits then you have to set the scale of fixnums and provide a decimal number as argument to the function sqrt. Examples follow:
: (sqrt 2) -> 1
: (sqrt 2.0)  -> 1414
: (format (sqrt 2.000) 3)  -> "1.414"

Complex Arithmetic Expressions.
PicoLisp supports complex arithmetic expressions such as the following :
7 + 2 – 4 + 6 -2 which must be expressed as :  (- ( + (- (+ 7 2) 4) 6) 2)

Comparing Numbers to zero.
In order to compare numbers to zero you can use the following functions: lt0, le0, ge0, gt0, =0, n0.
lt0 → less than zero. This function returns its argument when it is less than zero and NIL otherwise.
: (lt0 -23) -> -2 3
: (lt0 23) -> NIL
le0 → less or equal to zero. This function returns its argument when it is less or equal to zero and NIL otherwise.
: (le0 0) -> 0
: (le0 -4) -> -4
: (le0 34) -> NIL
ge0 → greater or equal to zero. This function returns its argument if it is greater or equal to zero and NIL otherwise.
: (ge0 0) -> 0
: (ge0 45) -> 45
: (ge0 -23) -> NIL
gt0 → greater than zero. This function returns its argument if it is greater than zero and NIL otherwise.
: (gt0 0)  -> NIL
: (gt0 89) -> 89
: (gt0 -55) -> NIL
=0 → equal to zero. This function returns its argument if it is zero and NIL otherwise.
: (=0 3)   -> NIL
: (=0 0)   -> 0
: (=0 -4) -> NIL
n0 → not zero. This function returns T if its argument is not zero and NIL otherwise.
: (n0 0)  -> NIL
: (n0 7)   -> T
: (n0 -33) -> T

Comparing Numbers.
PicoLisp uses the following functions for number comparison: =, <>, >, >=, <, <=.
= → equal. This function returns T if all of its arguments are equal.
: (= 1 2 3) -> NIL
: (= 1 1)   -> T
: (= 1 1 1) -> T
: (= 1 1 2) -> NIL
<> → different. This function returns T if not all of its arguments are equal.
: (<> 1 2) -> T
: (<> 1 1 1) -> NIL
: (<> 0 0 3)  -> T
> → greater. This function return T if all its arguments are in decreasing order.
: (> 1 2 3) -> NIL
: (> 4 3 2 1) -> T
: (> 4 4 3 2 1) -> NIL
>= → greater or equal.
: (>= 4 4 3 2 1) → T
< → smaller. This function returns T if all its arguments are in increasing order.
: (< 1 2 3)    -> T
: (< 3 2 1)   -> NIL
: (< 1 2 3 3) -> NIL
<= → smaller or equal.
: (<= 4 4 3 2 1) -> NIL
: (<= 1 1 2 3 4) -> T

Mathematical Functions.
More mathematical functions are available loading the following library math.l
: (load "/usr/lib/picolisp/lib/math.l") -> atan2
This mathematical library provides the following functions :
pow, exp, log, sin, cos, tan, asin, acos, atan, atan2.

: (sin (/ pi 4)) -> 707107
: (format (sin (/ pi 4)) *Scl) -> "0.707107"
: (format (cos (/ pi 4)) *Scl) -> "0.707107"
: (format (tan (/ pi 4)) *Scl) -> "1.000000"

Notes.
Notes adopted from "PicoLisp by Example", Alexander Burger, Thorsten Jolitz

Note 1.
*Scl
A global variable holding the current fixpoint input scale. See also Numbers
and scl.
Note 2.
(setq var ’any ..) -> any
Stores new values any in the var arguments. See also set, val and def.
Note 3.
(format ’num [’cnt [’sym1 [’sym2]]]) -> sym
(format ’sym|lst [’cnt [’sym1 [’sym2]]]) -> num
Converts a number num to a string, or a string sym|lst to a number. In both
cases, optionally a precision cnt, a decimal-separator sym1 and a thousands-
separator sym2 can be supplied. Returns NIL if the conversion is unsuccess-
ful. See also Numbers and round.