This tutorial tried to give a more thorough and deeper look at Maxima. I assume that you are already familiar with the basics of Maxima and symbolic expressions.
We will either use the direct mode or symbolic expressions here.
A Maxima expression consists of basic atoms and operators. You can check the type of an atom in various ways.
To save place, we often put several commands in a list.
>&[atom(x),atom(12),atom(12/7),atom(2.0),atom("string")]
[true, true, false, true, true]
To check for the type there are several commands.
symbolp, integerp, evenp, oddp, primep, floatnump, numberp, ratnump, constantp, stringp
>&[symbolp(x),integerp(45),oddp(45),primep(57),floatnump(1.0),constantp(x)]
[true, true, true, false, true, false]
To convert numbers to floats or big floats there are the following functions.
float, bfloat, round, floor, ceiling, string, eval_string
>&[float(pi),bfloat(pi)]
[3.141592653589793, 3.1415926535897932384626433832795b0]
Note that the constants of Maxima in EMT are pi, E, and I (or the default %pi, %e, %i).
>&[round(pi),floor(pi),ceiling(pi),string(pi),eval_string("E^(2*I)")]
2 I [3, 3, 4, pi, E ]
There are more constants for limits. For plus and minus infinity there are inf and minf. (The constant infinity is reserved for the complex infinity.)
>&limit((1+1/n)^n,n,inf)
E
There are some system constants. E.g., fpprec sets the precision of the big floating type.
You set constants with &:= if you want to have the value in numerical expressions of EMT too.
>fpprec &:= 50; &bfloat(pi)
3.1415926535897932384626433832795028841971693993751b0
Of course, we can also use the direct mode. Then the constant is not available in the numerical part of EMT, only in Maxima and symbolic expressions.
>:: fpprintprec:=5; float(pi)
3.1416
The default for this is 0 (full precision).
>:: fpprintprec:=0; float(pi)
3.141592653589793
To transfer floating point numbers to rationals, use ratsimp(). By default, the function works very precisely. But is is possible to relax the accuracy.
>:: ratepsilon:=0.001; ratsimp(1/7+1e-5)
rat: replaced 0.1428671428571429 by 1/7 = 0.1428571428571428 1 - 7
This message is suppressed in symbolic expressions, by the way.
>&ratsimp(1/7+1e-5)
1 - 7
Changing the output base is also possible. Do not forget to revert this to the default 10!
>:: obase:=16; 2345, obase:=10;
929
>printhex(2345,>integer)
929
Operators stand between expressions. If there are no brackets the order of evaluations depends on the binding power of the operator.
>&2+4*2
10
The order (left to right or right to left) is also an important property of an operator. E.g., the power operator is evaluated right to left in Maxima and EMT (but not in Matlab).
>&2^3^4, &2^(3^4), &(2^3)^4
2417851639229258349412352 2417851639229258349412352 4096
Some evaluations are done immediately if expressions with basic operators are involved.
>&x+2+x+a
2 x + a + 2
There are also operators with on argument. They can stand in front of the expression (prefix like "-x") or behind it (postfix). E.g., the factorial function is a "unary postfix operator".
>&40!
815915283247897734345611269596115894272000000000
The assignment is an operator in Maxima. On the left side must be a variable (not a value). The direct non-compatible mode uses ":" for assignments, while the compatibility uses ":=".
>:: u := 20; u^2
400
But you can use ":" in symbolic expressions, if you like.
>$u:30; &u^2
900
There are also logical operators. Note, that "=" is used instead of "==" as in EMT. This is used in solve().
>&solve(x^2=x,x)
[x = 0, x = 1]
The operator "=" does evaluate. But with "is" it can be forced to evaluate. In the example, we use the usual logical operators "and", "or", "not".
>&is(pi>3 and not pi>4)
true
Be careful, however, to compare two equations which are the same algebraically.
>e1 &= a+1/a; e2 &= (a^2+1)/a; &is(e1=e2), &is(equal(e1,e2))
false true
Another option is to put both to the same form.
>&ratsimp(e1), &is(%=e2)
2 a + 1 ------ a true
It is easy to define a function in Maxima. You can use the "function" keyword of EMT.
>function f(x) &= x^3/(x+1)
3 x ----- x + 1
This function is defined as a numerical function too.
To define the function only for symbolic purposes (purely symbolic) use &&=. In this case the function body is not evaluated at the time of the definition.
>function fs(y,x) &&= diff(y,x)
diff(y, x)
This would not work with &=, since diff(y,x) evaluates to 0, if y is constant.
Both definitions are translated to the original syntax in Maxima. The first one uses def(f(x),expr) which evaluated the expression.
>::: define(f(x),factor(diff(x^3/(x+1),x)));
2 x (2 x + 3) f(x) := ------------ 2 (x + 1)
The purely symbolic expression used :=.
>::: fs(y,x) := diff(y,x)
fs(y, x) := diff(y, x)
Most of the time, you should use symbolic or purely symbolic function in EMT with the keyword "function".
A function can be made an operator in EMT. You can simply set "prefix", "infix" or "postfix" in the function definition.
>function prefix cube (x) &= x^3
3 x
The the function can be used like a prefix operator.
>&cube 7
343
The definition in Maxima uses the functions prefix(f), infix(f), postfix(f). The infix() function can take "binding "powers" to the left and to the right. These powers define the order of the evaluation. The multiplication has power 120, and the addition 100.
>:: mymod (x,y) := mod(x,y); infix("mymod",90,90); >:: 100+1 mymod 3*5 // mod(101,15)
11
Maxima knows also matchfix().
>:: matchfix("--","--"); --x-- := cabs(x); --1+I--
--I + 1--
This will also work in symbolic expressions.
>&--1+I--
--I + 1--
Note that it is not possible to use |x| in Maxima in EMT in symbolic expressions or compatible direct mode, since | has a different meaning. It is replaced by a comma for the evaluation (as explained in the introduction to Maxima in EMT). This is so because the comma is the command separator in EMT.
>&(x^2-1)/(x+1) | ratsimp
x - 1
We are not going to discuss predicates of operators or "nary" operators in this tutorial.
Many functions evaluate immediately. To prevent this there is the operator '.
For the example, we load the function lcm() (least common multiplier) from the library "functs".
>&load("functs"); &lcm(17^4*18^3,3^6*17), &'(factor(%))
487094472 3 6 4 2 3 17
The operator ' can be used to prevent execution of functions too.
>&exp(-x^2)*x; &'diff(%,x) = factor(diff(%,x))
2 2 d - x 2 - x -- (x E ) = (1 - 2 x ) E dx
This is especially useful for Latex output. Here is a Latex formula in a comment.
It is done with
maxima: 'integrate(x*exp(-x),x,0,1) = integrate(x*exp(-x),x,0,1)
Latex for Maxima commands can also be used on the command line. Note that the Latex code is generated by Maxima.
>$'diff(x/(x+1),x,2)=factor(diff(x/(x+1),x,2))
For the solution of ordinary differential equations with ode2() the ' is very important. Note that diff(y,x) is 0 if y has no value, or not useful if y has a value.
>&ode2('diff(y,x)+y=x,y,x)
- x x y = E ((x - 1) E + %c)
The laws of sine and cosine are known to the simplifier trigsimp().
>&trigsimp(sin(x)^2+cos(x)^2)
1
Some simplifications are done automatically.
>&tan(asin(x))
x ------------ 2 sqrt(1 - x )
To convert to powers of trigonometric functions and back to Fourier series is possible too. But we must clean the solution with ratsimp() sometimes.
>&trigexpand(sin(5*x)), &ratsimp(trigreduce(%))
5 2 3 4 sin (x) - 10 cos (x) sin (x) + 5 cos (x) sin(x) sin(5 x)
The trigonometric and the hyperbolic functions can be converted to exponentials.
>&exponentialize(sin(x)^2), &expand(exponentialize(sinh(x)^2))
I x - I x 2 (E - E ) - ---------------- 4 2 x - 2 x E E 1 ---- + ------ - - 4 4 2
There are various functions to decompose expressions, or get information about expressions.
>&(x+1)/(x-1), &[op(%),first(%),part(%,2),listofvars(%),args(%),length(%)]
x + 1 ----- x - 1 [/, x + 1, x - 1, [x], [x + 1, x - 1], 2]
For equations there is rhs and lhs.
>&y+1=x^2+2; &[lhs(%),rhs(%)]
2 [y + 1, x + 2]
It is often easier to use "with".
>&solve(y+6=(5*x-3)/x,x), &x^2 with %
3 [x = - -----] y + 1 9 -------- 2 (y + 1)
Lists are created with [...]. There are many functions for lists.
>&[a,b,c]; &[%[2],length(%),first(%)]
[b, 3, a]
To create a list, use makelist().
>ls &= makelist(k^2,k,1,10)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Just as EMT, Maxima applies operators to lists element by element.
>&[1,2]+[a,b], &sin([1,2])
[a + 1, b + 2] [sin(1), sin(2)]
This works for functions too.
>function f(x) &= x^3-x; ... &f([1,2,3,4])
[0, 6, 24, 60]
There are also functions to search in a list.
>&member(16,makelist(k^2,k,1,10))
true
Functions can be used to check the elements of a list too.
>ls &= makelist(k^2+1,k,1,50), &some(primep,ls)
[2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170, 197, 226, 257, 290, 325, 362, 401, 442, 485, 530, 577, 626, 677, 730, 785, 842, 901, 962, 1025, 1090, 1157, 1226, 1297, 1370, 1445, 1522, 1601, 1682, 1765, 1850, 1937, 2026, 2117, 2210, 2305, 2402, 2501] true
Which ones are primes?
>&sublist(ls,primep)
[2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]
We just mention that the same can be done in EMT with an index vector.
>lsn=(1:50)^2+1; lsn[nonzeros(isprime(lsn))]
[2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601]
Note that the following would also work to get a list of values from Maxima. Because "ls" has been defined with "&=" it is an expression in EMT.
>ls()
[2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170, 197, 226, 257, 290, 325, 362, 401, 442, 485, 530, 577, 626, 677, 730, 785, 842, 901, 962, 1025, 1090, 1157, 1226, 1297, 1370, 1445, 1522, 1601, 1682, 1765, 1850, 1937, 2026, 2117, 2210, 2305, 2402, 2501]
We could also get the symbolic value of Maxima with &ls. Since we want to evaluate this in one expression, we need to use the following syntax.
>&"ls"()
[2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170, 197, 226, 257, 290, 325, 362, 401, 442, 485, 530, 577, 626, 677, 730, 785, 842, 901, 962, 1025, 1090, 1157, 1226, 1297, 1370, 1445, 1522, 1601, 1682, 1765, 1850, 1937, 2026, 2117, 2210, 2305, 2402, 2501]
The following is a purely symbolic functions (because primep() is named isprime() in EMT).
>function f(x) &&= primep(x) and x>5
primep(x) and (x > 5)
We can map such a function to a list.
>&map(f,makelist(k,k,1,10))
[false, false, false, false, false, false, true, false, false, false]
Another option is to use lambda functions. Such functions are like function objects in Maxima.
>&map(lambda([x],x^2),makelist(k,k,1,10))
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
So far, we used only expressions. For more elaborate programs, you will need blocks. A block is a list of expressions. The return value is the last expression.
>&block(a:x^3,a^2)
6 x
We used : to assign to a here. But := would work too. Note that the assignment has the global effect that a gets a value.
>&a
3 x
A block with local variables prevents this.
>&block([a],a:=x^4,a^2); &a
3 x
Maxima has "if" and "else".
>function f(x) &&= if x>=1 then x else 1;
This purely symbolic function can be mapped to a list.
>&map(f,[-2,-1,0,1,2])
[1, 1, 1, 1, 2]
Sometimes, we want to apply a purely symbolic function to a numerical vector. For short vectors, this can be done with "@var".
>x=0:0.01:2; plot2d(x,&"map(f,@x)"()):
For large vectors, mxmset() should be used. The conversion is done numerically, of course.
>mxmset("xv",x); &xv[50]
0.4900000000000003
Blocks can be left with "return". The following also shows how blocks can be spread over multi-lines in EMT.
>&block([x],x:=85*167/8, ... if x>1000 then return(x^2), ... "Not greater than 1000!")
201498025 --------- 64
Maxima has loops too.
>&block([sum], sum:=0, for k:=1 thru 10 do sum:=sum+k, sum)
55
Besides and optional "step" value, there is also a "next" statement.
>&block([sum], sum:=0, for k:=1 next 3*k+1 thru 1000 do sum:=sum+k, sum)
543
This is the same as the following in EMT.
>iterate("3*x+1",1,till="x>1000",n=1000), sum(head(%,-2))
[1, 4, 13, 40, 121, 364, 1093] 543
Note that display() or disp() (to show intermediate values in a loop or block) does not work in symbolic expressions. You need to use the direct mode.
>:: block([x],x:6,display(x),x^3)
x = 6 216