- Terminology
- Indicing
- Infix Notation
- Examples and
Print
- ~ (tilde suffix)
- Vector vs Vector~
- Equal To and Not Equal To (=, ≠, ≡, and ≢)
- Other Conventions
- Skip to Library Reference
The (otus algebra)
library operates slightly different terms for the objects it uses than Lisp, Lua, C, or Python.
All algebra objects are divides into:
- Scalars, the any kind of numbers - integers, rational (
17/3
), complex (3+7i
); in decimal, binary, octal, or hexadecimal notation- the
Scalar?
predicate returns#true
for all and only scalars
- the
- Arrays, any smart objects that allow indexed access to their parts (using the
Ref
function)- the
Array?
predicate returns#true
for all and only arrays
- the
- All other non-math objects (strings, booleans, lists, etc.)
All objects that mathematicians call vector, matrix, hypermatix, etc. are the Arrays in terms of algebra library. Ol vectors (started with lower-case 'v') are internal Ol objects that may be, or may not be the Array (from the capital 'A').
All math objects in Ol are indexed starting from 1 (one), just as mathematicians do! Not from 0 (zero), like programmers. Negative index means "counting from the end of".
> (Ref [10 11 12] 1)
10
> (Ref [10 11 12] -1)
12
You can use traditional infix math notation freely, if you want. Just use \\
macro (which is short for infix-notation
macro name).
> (\\ 2 * (3 + 4) )
14
> (infix-notation ; the same as \\
[1 2 3] + [4 5 6] )
[5 7 9]
Examples in this and subsequent reference docs are provided in form named "REPL" using prompt symbol "> ", which shows the behavior like if someone were typing code in an interactive ol session.
Please pay attention that print
ed values of fast (inexact) algebra arrays differ from REPL output. That's happen because the fast versions of algebra math objects have their own internal format that depends on the hardware used and is not intended to be read by humans. So you should use the special Print
function to display them in a real readable way.
> (define x (Vector~ [1 2 3]))
> x
[1.0 2.0 3.0]
; the ol 'print' output
> (print x)
'((3) . #u8(0 0 128 63 0 0 0 64 0 0 64 64))
; the algebra 'Print' output
> (Print x)
[1.0 2.0 3.0]
Names of algebra functions begins with capital letter, and Lisp functions with lower case.
The (otus algebra)
library operates on two major kind of numbers: exact numbers and inexact numbers. Exact numbers do not loose their precision during math transformations. But inexact numbers may do.
; exact number
> (define a 1e34)
> a
10000000000000000000000000000000000
; inexact number ('#i' is an explicit prefix for such numbers)
> (define b #i1e34)
> b
1.0e34
; exact calculations
> (\\ a + 2 - a)
2
; inexact calculations
> (\\ b + 2 - b)
0.0
As an undeniable benefit, inexact numbers math is highly optimized and fast (especially for very big and very small numbers or vectors).
Many functions have a special form of name that causes them to explicitly produce inexact numbers. It includes the tilde (~
) as a function suffix.
; a vector of exact numbers
> (Vector [1 2 3])
[1 2 3]
; a vector of inexact numbers
> (Vector [#i1 #i2 #i3])
[1.0 2.0 3.0]
; a fast vector of inexact numbers (explicitly)
> (Vector~ [1 2 3])
[1.0 2.0 3.0]
; it is impossible to create a
; fast vector of exact numbers
By default, (otus algebra)
uses exact math. You can change default behavior with:
-
Set environment variable
OTUS_ALGEBRA_DEFAULT_EXACTNESS
with "0", "False", "1", or "True" value:# with global variable set $ export OTUS_ALGEBRA_DEFAULT_EXACTNESS=0 $ ol your-evaluations.lisp # or with just running session variable $ OTUS_ALGEBRA_DEFAULT_EXACTNESS=False ol your-evaluations.lisp
-
Directly in the lisp code (
#t
to override possible previously assigned value,#f
to not):(import (scheme process-context)) (set-environment-variable! "OTUS_ALGEBRA_DEFAULT_EXACTNESS" "0" #t)
The default exactness cannot be changed once the (otus algebra)
library is loaded.
Maker and Maker~ may produce different arrays depending on the default-exactness option and existing of the compiled library:
- Maker produce exact array if default-exactness is true, and works as Maker~ otherwise.
- Maker~ ignore default-exactness option (
~
is an explicit choose), and- makes fast (c) array with inexact components, if fast library loaded,
- makes regular (lisp) array with inexact components, if fast library not loaded.
So, briefly: Maker works as exact or inexact depending on default-exactness option, Maker~ always works as inexact, but depends on fast library existent.
You can compare objects using =
and ≠
signs. These operators don't distinct exact and inexact arrays and tries to compare them in usual way. It may produce false results, if you mix exact and inexact math.
> 3.3
33/10
> #i3.3
3.29999999
> (= 3.3 #i3.3)
#true
> (= [1 2 3] (Array~ [1 2 3]))
#true
If you want to keep under control such comparisons, you must use ≡
and ≢
signs. These operators compare only objects with same type - exacts with exacts, and inexacts with inexacts.
> (≡ 3.3 #i3.3)
#false
> (≡ [1 2 3] (Array~ [1 2 3]))
#false
The (otus algebra)
functions begin with a capital letter to distinguish them from the ol functions which are in a lowercase.
Mutators (typically ends with "!
" suffix) applicable only to enums (positive and negative values) and inexacts. Mutators are dangerous and giving no real benefit. Use them only if you really understand what you are doing.
Fast vectors, matrices and tensors are supported, of course, without any restrictions.
; a heterogeneous vector
> (define x [3 4/5 7 #i12.34])
> x
[3 4/5 7 12.3399999]
; let's fill with exact number "1",
; you see, inexact number changed too
> (Fill! x 1)
[1 4/5 1 1.0]
; and now with inexact number,
; exact numbers are not changed
> (Fill! x #i7.42)
[1 4/5 1 7.41999999]
- Why inexact number
#i1e14
prints as1.0e14
, but#i1e15
as10.0e14
?
Because of nature of imprecise hardware calculations.
Some native Lisp objects are supported too:
- Strings, any unicode or regular (ansi) strings emphasized with
"
- the
string?
predicate returns#true
for all and only strings
- the
- Functions, any program objects that can be called with or without argument(s) to produce result(s)
- the
function?
predicate returns#true
for all and only functions - predicates are functions too
- the