In> DefaultDirectory("/home/user/myscripts/"); Out> True; |
In> Taylor(x,0,5)Sin(x) Out> x-x^3/6+x^5/120; In> PrettyPrinter("PrettyForm"); True Out> In> Taylor(x,0,5)Sin(x) 3 5 x x x - -- + --- 6 120 Out> In> PrettyPrinter(); Out> True; In> Taylor(x,0,5)Sin(x) Out> x-x^3/6+x^5/120; |
Help(_f) <-- SystemCall("netscape ":FindFile("documentation/ref.html"):"#":f); Help() := SystemCall("netscape ":FindFile("documentation/books.html")); |
In> HistorySize(200) Out> True; In> quit |
In> 2+3 Out> 5; In> 2*3 Out> 6; |
In> Div(5,3) Out> 1; In> Mod(5,3) Out> 2; |
Routine for calculating Gcd(n,m) 1) if n = m then return n 2) if both n and m are even then return 2*Gcd(n/2,m/2) 3) if exactly one of n or m (say n) is even then return Gcd(n/2,m) 4) if both n and m are odd and, say, n>m then return Gcd( (n-m)/2,m) |
Gcd({a,b,c}) = Gcd(Gcd(a,b),c) |
In> Gcd(55,10) Out> 5; In> Gcd({60,24,120}) Out> 12; |
Lcm(n,m) = Div(n*m,Gcd(n,m)) |
In> Lcm(60,24) Out> 120; |
Examples: 1<<10; should evaluate to 1024 -1024>>10; should evaluate to -1 |
These functions use the p-adic expansion capabilities of the built-in arbitrary precision math libraries.
In> FromBase(2,111111) Out> 63; In> ToBase(16,255) Out> ff; |
In> Precision(10) Out> True; In> N(Sin(1)) Out> 0.8414709848; In> Precision(20) Out> True; In> N(Sin(1)) Out> 0.84147098480789650665; In> GetPrecision() Out> 20; |
In addition, the variable Pi is bound to the value of pi up to the required precision.
In> 1/2 Out> 1/2; In> N(1/2) Out> 0.5; In> Sin(1) Out> Sin(1); In> N(Sin(1),10) Out> 0.8414709848; In> Pi Out> Pi; In> N(Pi,20) Out> 3.14159265358979323846; |
It does this by finding the smallest integer n such that multiplying the number with 10^n is an integer. Then it divides by 10^n again, depending on the internal gcd calculation to reduce the resulting division of integers.
In> Sin(1.234) Out> Sin(1.234); In> Rationalize(%) Out> Sin(617/500); |
The result of Factors is a list of lists of the form {p,n}, where each p^n divides the original x.
Factor shows the result of Factors in a nicer human readable format.
In> Factors(12) Out> {{2,2},{3,1}}; In> PrettyForm(Factor(12)) 2 2 * 3 |
n = a0 +a1*p +a2*p^2+...
So for instance
In> PrettyForm(PAdicExpand(1234,10)) 2 3 4 + 3 * 10 + 2 * 10 + 10 Out> True; |
In> PrettyForm(ContFrac(N(Pi))) 1 3 + --------------------------- 1 7 + ----------------------- 1 15 + ------------------ 1 1 + -------------- 1 292 + -------- 1 + rest |
In> Decimal(1/22) Out> {0,0,{4,5}}; In> N(1/22,30) Out> 0.045454545454545454545454545454; |
The library uses the formula
/ r \ r - MathFloor| ------ | * 2 * Pi \ 2 * Pi / |
In> 2*Pi() Out> 6.283185307; In> TruncRadian(6.28) Out> 6.28; In> TruncRadian(6.29) Out> 0.0068146929; |
In> Floor(1.1) Out> 1; In> Floor(-1.1) Out> -2; |
In> Ceil(1.1) Out> 2; In> Ceil(-1.1) Out> -1; |
In> Round(1.49) Out> 1; In> Round(1.51) Out> 2; In> Round(-1.49) Out> -1; In> Round(-1.51) Out> -2; |
In> Pslq({ 2*Pi+3*Exp(1) , Pi , Exp(1) },20) Out> {1,-2,-3}; |
Yacas knows some trigonometric identities, so it can simplify to exact results even if N is not used. This is the case when the arguments are of the form Pi, Pi/2 etcetera.
In> Sin(1) Out> Sin(1); In> N(Sin(1),20) Out> 0.84147098480789650665; In> Sin(Pi/4) Out> Sqrt(2)/2; |
In> Exp(2) Out> Exp(2); In> Ln(%) Out> 2; |
In> Sqrt(16) Out> 4; In> Sqrt(15) Out> Sqrt(15); In> N(Sqrt(15)) Out> 3.8729833462; |
In> Abs(-2) Out> 2; In> Sign(-2) Out> -1; |
Complex(x,y) is the internal representation of a complex number in Yacas.
Arg returns the angle a for which the complex number is amp*(Cos(angle) + I*Sin(angle)). As such it returns an angle from -Pi to +Pi.
In> z := 2+3*I Out> Complex(2,3); In> Re(z) Out> 2; In> Im(z) Out> 3; In> Arg(Exp(I*Pi/3)) Out> Pi/3; |
In> 10! Out> 3628800; In> Bin(10,4) Out> 210; In> (10!)/((6!)*(4!)) Out> 210; In> (3/2)! Out> (3*Sqrt(Pi))/4; |
Iteration can either proceed over the elements of a list passed in, or by evaluating 'body' by iterating variable 'var' from value 'from' upto 'to'. 'to' should be greater than or equal to from.
In> Sum(i,1,3,i) Out> 6; In> Sum({1,2,3}) Out> 6; In> Sum(1 .. 3) Out> 6; In> Average(1 .. 3) Out> 2; In> Factorize(i,1,3,i) Out> 6; In> Factorize({1,2,3}) Out> 6; In> Factorize(1 .. 3) Out> 6; |
In> Min(2,3) Out> 2; In> Max(2,3) Out> 3; In> Min(5 .. 15) Out> 5; In> Max(5 .. 15) Out> 15; |
In> IsRational(a) Out> False; In> IsRational(a/b) Out> True; In> Numer(a/b) Out> a; In> Denom(a/b) Out> b; |
In> Commutator(2,3) Out> 0; In> m1:=Identity(3) Out> {{1,0,0},{0,1,0},{0,0,1}}; In> m1[1][2] := a Out> True; In> m2:=Identity(3) Out> {{1,0,0},{0,1,0},{0,0,1}}; In> m2[2][2] := a Out> True; In> Commutator(m1,m2) Out> {{0,a^2-a,0},{0,0,0},{0,0,0}}; |
In> Taylor(x,0,9)Sin(x) 3 5 7 9 x x x x x - -- + --- - ---- + ------ 6 120 5040 362880 Out> |
In> exp1 := Taylor(x,0,7)Sin(x) 3 5 7 x x x x - -- + --- - ---- 6 120 5040 Out> In> exp2 := InverseTaylor(x,0,8)ArcSin(x) 5 7 3 x x x --- - ---- - -- + x 120 5040 6 Out> In> Simplify(exp1-exp2) 0 Out> |
This function is used to determine the taylor series expansion of a function: if g(var)=var, then h(f(var))=var, so h will be the inverse of f.
In> f(x):=Eval(Expand((1+x)^4)) Out> True; In> g(x) := x^2 Out> True; In> h(y):=Eval(ReversePoly(f(x),g(x),x,y,8)) Out> True; In> BigOh(h(f(x)),x,8) Out> x^2; In> h(x) Out> (-2695*(x-1)^7)/131072+(791*(x-1)^6)/32768+(-119*(x-1)^5)/4096+(37*(x-1)^4)/1024+(-3*(x-1)^3)/64+(x-1)^2/16; |
In> BigOh(1+x+x^2+x^3,x,2) Out> x+1; |
In> Newton(Sin(x),x,3,0.0001) Out> 3.1415926535; |
In> D(x)Sin(x*y) Out> y*Cos(x*y); In> D({x,y,z})Sin(x*y) Out> {y*Cos(x*y),x*Cos(x*y),0}; In> D(x,2)Sin(x*y) Out> -Sin(x*y)*y^2; In> D(x){Sin(x),Cos(x)} Out> {Cos(x),-Sin(x)}; |
In> Diverge({x*y,x*y,x*y},{x,y,z}) Out> {y,x,0}; In> Curl({x*y,x*y,x*y},{x,y,z}) Out> {x,-y,y-x}; |
In> Integrate(x,a,b)Cos(x) Out> Sin(b)-Sin(a); In> Integrate(x)Cos(x) Out> Sin(x)+C9; |
In> a*b*a^2/b-a^3 Out> (b*a^3)/b-a^3; In> Simplify(a*b*a^2/b-a^3) Out> 0; |
In> RadSimp(Sqrt(9+4*Sqrt(2))) Out> 1+Sqrt(8); In> RadSimp(Sqrt(5+2*Sqrt(6))+Sqrt(5-2*Sqrt(6))) Out> Sqrt(12); In> RadSimp(Sqrt(14+3*Sqrt(3+2*Sqrt(5-12*Sqrt(3-2*Sqrt(2)))))) Out> 3+Sqrt(2); |
In> {1.2,3.123,4.5} Out> {1.2,3.123,4.5}; In> Rationalize(%) Out> {6/5,3123/1000,9/2}; |
In> Solve(a+x*y==z,x) Out> (z-a)/y; In> Solve({a*x+y==0,x+z==0},{x,y}) Out> {{-z,z*a}}; |
In> SuchThat(a+b*x,x) Out> (-a)/b; In> SuchThat(Cos(a)+Cos(b)^2,Cos(b)) Out> (-Cos(a))^(1/2); In> Expand(a*x+b*x+c,x) Out> c+(a+b)*x; In> SuchThat(%,x) Out> (-c)/(a+b); |
In> Subst(Cos(b),c)(Sin(a)+Cos(b)^2/c) 2 c Sin( a ) + -- c Out> In> Eliminate(Cos(b),c,Sin(a)+Cos(b)^2/c) Sin( a ) + c Out> |
In> PSolve(b*x+a,x) Out> -a/b; In> PSolve(c*x^2+b*x+a,x) Out> {(Sqrt(b^2-4*c*a)-b)/(2*c),(-(b+Sqrt(b^2-4*c*a)))/(2*c)}; |
In> Pi() Out> 3.14159265358979323846; In> Precision(40) Out> True; In> Pi() Out> 3.1415926535897932384626433832795028841971; |
In> VarList(Sin(x)) Out> {x}; In> VarList(x+a*y) Out> {x,a,y}; |
You can also specify a direction for the limit, Left or Right. Specifying Right will take the limit from positive Infinity, and Left will take the limit from -Infinity.
In> Limit(x,0) Sin(x)/x Out> 1; In> Limit(x,0) (Sin(x)-Tan(x))/(x^3) Out> -1/2; In> Limit(x,0)1/x Out> Undefined; In> Limit(x,0,Left)1/x Out> -Infinity; In> Limit(x,0,Right)1/x Out> Infinity; |
It also tries to simplify the resulting expression as much as possible, trying to combine all like terms.
This function is used in for instance Integrate, to bring down the expression into a simpler form that can be integrated easily.
In> TrigSimpCombine(Cos(a)^2+Sin(a)^2) 1 Out> In> TrigSimpCombine(Cos(a)^2-Sin(a)^2) Cos( 2 * a ) Out> In> TrigSimpCombine(Cos(a)^2*Sin(b)) Sin( b ) Sin( -2 * a + b ) Sin( -2 * a - b ) -------- + ----------------- - ----------------- 2 4 4 Out> |
This routine uses the Lagrange interpolant formula to build up the polynomial.
In> LagrangeInterpolant({x1,x2,x3},{y1,y2,y3},x) y1 * ( x - x2 ) * ( x - x3 ) y2 * ( x - x1 ) * ( x - x3 ) ---------------------------- + ---------------------------- ( x1 - x2 ) * ( x1 - x3 ) ( x2 - x1 ) * ( x2 - x3 ) y3 * ( x - x1 ) * ( x - x2 ) + ---------------------------- ( x3 - x1 ) * ( x3 - x2 ) Out> |
In> Fibonacci(4) Out> 3; In> Fibonacci(8) Out> 21; |
In> LeviCivita({1,2,3}) Out> 1; In> LeviCivita({2,1,3}) Out> -1; In> LeviCivita({2,2,3}) Out> 0; |
In> Permutations({a,b,c}) Out> {{a,b,c},{a,c,b},{c,a,b},{b,a,c},{b,c,a},{c,b,a}}; |
In> {a,b,c} . {d,e,f}; Out> a*d+b*e+c*f; |
In> {a,b,c} X {d,e,f}; Out> {b*f-c*e,c*d-a*f,a*e-b*d}; |
In> ZeroVector(4) Out> {0,0,0,0}; |
In> BaseVector(2,4) Out> {0,1,0,0}; |
In> Identity(3) Out> {{1,0,0},{0,1,0},{0,0,1}}; |
In> ZeroMatrix(3,4) Out> {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; |
In> DiagonalMatrix(1 .. 4) Out> {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; |
In> IsMatrix(ZeroMatrix(3,4)) Out> True; In> IsMatrix(ZeroVector(4)) Out> False; In> IsMatrix(3) Out> False; |
In> Normalize({3,4}) Out> {3/5,4/5}; In> % . % Out> 1; |
In> Transpose({{a,b}}) Out> {{a},{b}}; |
In> DiagonalMatrix(1 .. 4) Out> {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; In> Determinant(%) Out> 24; |
In> DiagonalMatrix(1 .. 4) Out> {{1,0,0,0},{0,2,0,0},{0,0,3,0},{0,0,0,4}}; In> Trace(%) Out> 10; |
In> DiagonalMatrix({a,b,c}) Out> {{a,0,0},{0,b,0},{0,0,c}}; In> Inverse(%) Out> {{(b*c)/(a*b*c),0,0},{0,(a*c)/(a*b*c),0},{0,0,(a*b)/(a*b*c)}}; In> Simplify(%) Out> {{1/a,0,0},{0,1/b,0},{0,0,1/c}}; |
In> A := {{1,2,3}, {4,5,6}, {7,8,9}}; Out> {{1,2,3},{4,5,6},{7,8,9}}; In> PrettyForm(A); / \ | ( 1 ) ( 2 ) ( 3 ) | | | | ( 4 ) ( 5 ) ( 6 ) | | | | ( 7 ) ( 8 ) ( 9 ) | \ / Out> True; In> Minor(A,1,2); Out> -6; In> Determinant({{2,3}, {8,9}}); Out> -6; |
In> A := {{1,2,3}, {4,5,6}, {7,8,9}}; Out> {{1,2,3},{4,5,6},{7,8,9}}; In> PrettyForm(A); / \ | ( 1 ) ( 2 ) ( 3 ) | | | | ( 4 ) ( 5 ) ( 6 ) | | | | ( 7 ) ( 8 ) ( 9 ) | \ / Out> True; In> CoFactor(A,1,2); Out> 6; In> Minor(A,1,2); Out> -6; In> Minor(A,1,2) * (-1)^(1+2); Out> 6; |
In> A := {{1,2}, {3,4}}; Out> {{1,2},{3,4}}; In> v := {5,6}; Out> {5,6}; In> x := SolveMatrix(A, v); Out> {-4,9/2}; In> A * x; Out> {5,6}; |
In> DiagonalMatrix({a,b,c}) Out> {{a,0,0},{0,b,0},{0,0,c}}; In> CharacteristicEquation(%,x) Out> (a-x)*(b-x)*(c-x); In> Expand(%,x) Out> (b+a+c)*x^2-x^3-((b+a)*c+a*b)*x+a*b*c; |
In> M:={{1,2},{2,1}} Out> {{1,2},{2,1}}; In> EigenValues(M) Out> {3,-1}; |
In> M:={{1,2},{2,1}} Out> {{1,2},{2,1}}; In> e:=EigenValues(M) Out> {3,-1}; In> EigenVectors(M,e) Out> {{-ki2/ -1,ki2},{-ki2,ki2}}; |
In> IsHermitean({{0,I},{-I,0}}) Out> True; In> IsHermitean({{0,I},{2,0}}) Out> False; |
In> IsUnitary({{0,I},{-I,0}}) Out> True; In> IsUnitary({{0,I},{2,0}}) Out> False; |
If the polynomial "expr" contains only one variable, the first calling sequence can be used. Otherwise, the second form should be used which explicitly mentions that "expr" should be considered as a polynomial in the variable "var". The third calling form can be used for multivariate polynomials. Firstly, the polynomial "expr" is expanded with respect to the first variable in "varlist". Then the coefficients are all expanded with respect to the second variable, and so on.
In> PrettyPrinter("PrettyForm"); True Out> In> Expand((1+x)^5); 5 4 3 2 x + 5 * x + 10 * x + 10 * x + 5 * x + 1 Out> In> Expand((1+x-y)^2, x); 2 2 x + 2 * ( 1 - y ) * x + ( 1 - y ) Out> In> Expand((1+x-y)^2, {x,y}); 2 2 x + ( -2 * y + 2 ) * x + y - 2 * y + 1 Out> |
In> Degree(x^5+x-1); Out> 5; In> Degree(a+b*x^3, a); Out> 1; In> Degree(a+b*x^3, x); Out> 3; |
In> e := Expand((a+x)^4,x) Out> x^4+4*a*x^3+(a^2+(2*a)^2+a^2)*x^2+(a^2*2*a+2*a^3)*x+a^4; In> Coef(e,a,2) Out> 6*x^2; In> Coef(e,a,0 .. 4) Out> {x^4,4*x^3,6*x^2,4*x,1}; |
In> poly := 2*x^2 + 4*x; Out> 2*x^2+4*x; In> c := Content(poly); Out> 2*x; In> pp := PrimitivePart(poly); Out> x+2; In> Expand(pp*c); Out> 2*x^2+4*x; |
In> poly := 2*x^2 + 4*x; Out> 2*x^2+4*x; In> c := Content(poly); Out> 2*x; In> pp := PrimitivePart(poly); Out> x+2; In> Expand(pp*c); Out> 2*x^2+4*x; |
In> poly := 2*x^2 + 4*x; Out> 2*x^2+4*x; In> lc := LeadingCoef(poly); Out> 2; In> m := Monic(poly); Out> x^2+2*x; In> Expand(lc*m); Out> 2*x^2+4*x; In> LeadingCoef(2*a^2 + 3*a*b^2 + 5, a); Out> 2; In> LeadingCoef(2*a^2 + 3*a*b^2 + 5, b); Out> 3*a; |
In> poly := 2*x^2 + 4*x; Out> 2*x^2+4*x; In> lc := LeadingCoef(poly); Out> 2; In> m := Monic(poly); Out> x^2+2*x; In> Expand(lc*m); Out> 2*x^2+4*x; In> Monic(2*a^2 + 3*a*b^2 + 5, a); Out> a^2+(a*3*b^2)/2+5/2; In> Monic(2*a^2 + 3*a*b^2 + 5, b); Out> b^2+(2*a^2+5)/(3*a); |
In> RandomPoly(x,3,-10,10) Out> 3*x^3+10*x^2-4*x-6; In> RandomPoly(x,3,-10,10) Out> -2*x^3-8*x^2+8; |
n-1 n c(0) + c(1) * x + ... + c(n-1) * x + c(n) * x |
(...( c(n) * x + c(n-1) ) * x + ... + c(1) ) * x + c(0) |
In> expr1:=Expand((1+x)^4) Out> x^4+4*x^3+6*x^2+4*x+1 In> Horner(expr1,x) Out> (((x+4)*x+6)*x+4)*x+1 |
In> Expand((a-x)*(b-x),x) Out> x^2-(b+a)*x+a*b; In> Expand((a-x)*(b-x),{x,a,b}) Out> x^2-(b+a)*x+b*a; In> ExpandBrackets((a-x)*(b-x)) Out> a*b-x*b+x^2-a*x; |
In> Head({a,b,c}) Out> a; In> Head(f(a,b,c)); Out> a; |
In> Tail({a,b,c}) Out> {b,c}; |
In> Length({a,b,c}) Out> 3; In> Length("abcdef"); Out> 6; |
In> MapSingle("Sin",{a,b,c}); Out> {Sin(a),Sin(b),Sin(c)}; In> Map("+",{{a,b},{c,d}}); Out> {a+c,b+d}; |
The /@ operator provides a shorthand for MapSingle.
In> MapSingle("Sin",{a,b,c}); Out> {Sin(a),Sin(b),Sin(c)}; In> MapSingle({{x},x^2}, {a,2,c}); Out> {a^2,4,c^2}; |
In> RandomIntegerVector(4,-3,3) Out> {0,3,2,-2}; |
In> MakeVector(a,3) Out> {a1,a2,a3}; |
In> Select("IsInteger",{a,b,2,c,3,d,4,e,f}) Out> {2,3,4}; |
More generally, Nth returns the n-th operand of the expression passed as first argument.
An alternative but equivalent form of Nth(list, n) is list[n].
In> lst := {a,b,c,13,19}; Out> {a,b,c,13,19}; In> Nth(lst, 3); Out> c; In> lst[3]; Out> c; In> Nth(lst, {3,4,1}); Out> {c,13,a}; In> Nth(b*(a+c), 2); Out> a+c; |
Destructive commands are faster than their nondestructive counterparts. Stangely, there is no nondestructive command to reverse a list. Use FlatCopy and DestructiveReverse to achieve this.
In> lst := {a,b,c,13,19}; Out> {a,b,c,13,19}; In> revlst := DestructiveReverse(lst); Out> {19,13,c,b,a}; In> lst; Out> {a}; |
In> List(); Out> {}; In> List(a,b); Out> {a,b}; In> List(a,{1,2},d); Out> {a,{1,2},d}; |
Note that "list" is evaluated before the function application is formed, but the resulting expression is not evaluated.
In> UnList({Cos, x}); Out> Cos(x); In> UnList({f}); Out> f(); In> UnList({Taylor,x,0,5,Cos(x)}); Out> Taylor(x,0,5)Cos(x); In> Eval(%); Out> 1-x^2/2+x^4/24; |
In> Listify(Cos(x)); Out> {Cos,x}; In> Listify(3*a); Out> {*,3,a}; |
In> Concat({a,b}, {c,d}); Out> {a,b,c,d}; In> Concat({5}, {a,b,c}, {{f(x)}}); Out> {5,a,b,c,{f(x)}}; |
In> Delete({a,b,c,d,e,f}, 4); Out> {a,b,c,e,f}; |
In> Insert({a,b,c,d}, 4, x); Out> {a,b,c,x,d}; In> Insert({a,b,c,d}, 5, x); Out> {a,b,c,d,x}; In> Insert({a,b,c,d}, 1, x); Out> {x,a,b,c,d}; |
Destructive commands run faster than their nondestructive counterparts because the latter copy the list before they alter it.
In> lst := {a,b,c,d,e,f}; Out> {a,b,c,d,e,f}; In> Delete(lst, 4); Out> {a,b,c,e,f}; In> lst; Out> {a,b,c,d,e,f}; In> DestructiveDelete(lst, 4); Out> {a,b,c,e,f}; In> lst; Out> {a,b,c,e,f}; |
Destructive commands run faster than their nondestructive counterparts because the latter copy the list before they alter it.
In> lst := {a,b,c,d}; Out> {a,b,c,d}; In> Insert(lst, 2, x); Out> {a,x,b,c,d}; In> lst; Out> {a,b,c,d}; In> DestructiveInsert(lst, 2, x); Out> {a,x,b,c,d}; In> lst; Out> {a,x,b,c,d}; |
In> Replace({a,b,c,d,e,f}, 4, x); Out> {a,b,c,x,e,f}; |
Destructive commands run faster than their nondestructive counterparts because the latter copy the list before they alter it.
In> lst := {a,b,c,d,e,f}; Out> {a,b,c,d,e,f}; In> Replace(lst, 4, x); Out> {a,b,c,x,e,f}; In> lst; Out> {a,b,c,d,e,f}; In> DestructiveReplace(lst, 4, x); Out> {a,b,c,x,e,f}; In> lst; Out> {a,b,c,x,e,f}; |
In> reverse(l_IsList) <-- DestructiveReverse(FlatCopy(l)); Out> True; In> lst := {a,b,c,d,e}; Out> {a,b,c,d,e}; In> reverse(lst); Out> {e,d,c,b,a}; In> lst; Out> {a,b,c,d,e}; |
In> Contains({a,b,c,d}, b); Out> True; In> Contains({a,b,c,d}, x); Out> False; In> Contains({a,{1,2,3},z}, 1); Out> False; In> Contains(a*b, b); Out> True; |
In> Find({a,b,c,d,e,f}, d); Out> 4; In> Find({1,2,3,2,1}, 2); Out> 2; In> Find({1,2,3,2,1}, 4); Out> -1; |
Note that due to the underlying data structure, the time it takes to append an entry at the end of a list grows linearly with the length of the list, while the time for prepending an entry at the beginning is constant.
In> Append({a,b,c,d}, 1); Out> {a,b,c,d,1}; |
Destructive commands run faster than their nondestructive counterparts because the latter copy the list before they alter it.
In> lst := {a,b,c,d}; Out> {a,b,c,d}; In> Append(lst, 1); Out> {a,b,c,d,1}; In> lst Out> {a,b,c,d}; In> DestructiveAppend(lst, 1); Out> {a,b,c,d,1}; In> lst; Out> {a,b,c,d,1}; |
In> RemoveDuplicates({1,2,3,2,1}); Out> {1,2,3}; In> RemoveDuplicates({a,1,b,1,c,1}); Out> {a,1,b,c}; |
In> stack := {}; Out> {}; In> Push(stack, x); Out> {x}; In> Push(stack, x2); Out> {x2,x}; In> PopFront(stack); Out> x2; |
In> stack := {}; Out> {}; In> Push(stack, x); Out> {x}; In> Push(stack, x2); Out> {x2,x}; In> Push(stack, x3); Out> {x3,x2,x}; In> Pop(stack, 2); Out> x2; In> stack; Out> {x3,x}; |
In> stack := {}; Out> {}; In> Push(stack, x); Out> {x}; In> Push(stack, x2); Out> {x2,x}; In> Push(stack, x3); Out> {x3,x2,x}; In> PopFront(stack); Out> x3; In> stack; Out> {x2,x}; |
In> stack := {}; Out> {}; In> Push(stack, x); Out> {x}; In> Push(stack, x2); Out> {x2,x}; In> Push(stack, x3); Out> {x3,x2,x}; In> PopBack(stack); Out> x; In> stack; Out> {x3,x2}; |
In> lst := {a,b,c,d,e,f}; Out> {a,b,c,d,e,f}; In> Swap(lst, 2, 4); Out> {a,d,c,b,e,f}; |
In> lst := {a,b,c,b,a}; Out> {a,b,c,b,a}; In> Count(lst, a); Out> 2; In> Count(lst, c); Out> 1; In> Count(lst, x); Out> 0; |
In> Intersection({a,b,c}, {b,c,d}); Out> {b,c}; In> Intersection({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); Out> {e,o,u}; In> Intersection({1,2,2,3,3,3}, {1,1,2,2,3,3}); Out> {1,2,2,3,3}; |
In> Union({a,b,c}, {b,c,d}); Out> {a,b,c,d}; In> Union({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); Out> {a,e,i,o,u,f,r,t,n}; In> Union({1,2,2,3,3,3}, {2,2,3,3,4,4}); Out> {1,2,3,4}; |
In> Difference({a,b,c}, {b,c,d}); Out> {a}; In> Difference({a,e,i,o,u}, {f,o,u,r,t,e,e,n}); Out> {a,i}; In> Difference({1,2,2,3,3,3}, {2,2,3,4,4}); Out> {1,3,3}; |
In> FillList(x, 5); Out> {x,x,x,x,x}; |
In> lst := {a,b,c,d,e,f,g}; Out> {a,b,c,d,e,f,g}; In> Drop(lst, 2); Out> {c,d,e,f,g}; In> Drop(lst, -3); Out> {a,b,c,d}; In> Drop(lst, {2,4}); Out> {a,e,f,g}; |
In> lst := {a,b,c,d,e,f,g}; Out> {a,b,c,d,e,f,g}; In> Take(lst, 2); Out> {a,b}; In> Take(lst, -3); Out> {e,f,g}; In> Take(lst, {2,4}); Out> {b,c,d}; |
In> Partition({a,b,c,d,e,f,}, 2); Out> {{a,b},{c,d},{e,f}}; In> Partition(1 .. 11, 3); Out> {{1,2,3},{4,5,6},{7,8,9}}; |
Association lists are represented as a list of two-entry lists. The first element in the two-entry list is the key, the second element is the value stored under this key.
The call Assoc(key, alist) can (probably more intuitively) be accessed as alist[key].
In> writer := {}; Out> {}; In> writer["Iliad"] := "Homer"; Out> True; In> writer["Henry IV"] := "Shakespeare"; Out> True; In> writer["Ulysses"] := "James Joyce"; Out> True; In> Assoc("Henry IV", writer); Out> {"Henry IV","Shakespeare"}; In> Assoc("War and Peace", writer); Out> Empty; |
In> writer := {}; Out> {}; In> writer["Iliad"] := "Homer"; Out> True; In> writer["Henry IV"] := "Shakespeare"; Out> True; In> writer["Ulysses"] := "James Joyce"; Out> True; In> AssocIndices(writer); Out> {"Iliad","Henry IV","Ulysses"}; |
In> Flatten(a+b*c+d,"+"); Out> {a,b*c,d}; In> Flatten({a,{b,c},d},"List"); Out> {a,b,c,d}; |
In> UnFlatten({a,b,c},"+",0) Out> a+b+c; In> UnFlatten({a,b,c},"*",1) Out> a*b*c; |
In> Type({a,b,c}); Out> "List"; In> Type(a*(b+c)); Out> "*"; In> Type(123); Out> ""; |
In> NrArgs(f(a,b,c)) Out> 3; In> NrArgs(Sin(x)); Out> 1; In> NrArgs(a*(b+c)); Out> 2; |
This function uses the so-called BubbleSort algorithm to do the sorting. This algorithm is chosen because it is easy to implement, though it is not particularly fast.
In> BubbleSort({4,7,23,53,-2,1}, "<"); Out> {-2,1,4,7,23,53}; In> BubbleSort({4,7,23,53,-2,1}, ">"); Out> {53,23,7,4,1,-2}; |
In> Table(i!, i, 1, 10, 1); Out> {1,2,6,24,120,720,5040,40320,362880,3628800}; In> Table(i, i, 3, 16, 4); Out> {3,7,11,15}; In> Table(i^2, i, 10, 1, -1); Out> {100,81,64,49,36,25,16,9,4,1}; |
In> TableForm(Table(i!, i, 1, 10, 1)); 1 2 6 24 120 720 5040 40320 362880 3628800 Out> True; |
In> a:b:c:{} Out> {a,b,c}; In> "This":"Is":"A":"String" Out> "ThisIsAString"; |
In> "Sin" @ a Out> Sin(a); In> {{a},Sin(a)} @ a Out> Sin(a); In> "f" @ {a,b} Out> f(a,b); |
In> "Sin" /@ {a,b} Out> {Sin(a),Sin(b)}; In> {{a},Sin(a)*a} /@ {a,b} Out> {Sin(a)*a,Sin(b)*b}; |
In> 1 .. 4 Out> {1,2,3,4}; |
The point of having a maximum evaluation depth is to catch any infinite recursion. For example, after the definition f(x) := f(x), evaluating the expression f(x) would call f(x), which would call f(x), etcetera. The interpreter will halt if the maximum evaluation depth is reached. Also indirect recursion, like the pair of definitions f(x) := g(x) and g(x) := f(x), will be caught.
In> f(x) := f(x) Out> True; In> f(x) Error on line 1 in file [CommandLine] Max evaluation stack depth reached. Please use MaxEvalDepth to increase the stack size as needed. |
However, a long calculation may cause the maximum evaluation depth to be reached without the presence of infinite recursion. The function MaxEvalDepth is meant for these cases.
In> 10 # g(0) <-- 1; Out> True; In> 20 # g(n_IsPositiveInteger) <-- 2 * g(n-1); Out> True; In> g(1001); Error on line 1 in file [CommandLine] Max evaluation stack depth reached. Please use MaxEvalDepth to increase the stack size as needed. In> MaxEvalDepth(10000); Out> True; In> g(1001); Out> 214301721437253464189685009812000362112280962341106721488750077674070210224 98722449863967576313917162551893458351062936503742905713846280871969155149397149 60786913554964846197084214921012474228375590836430609294996716388253479753511833 1087892154125829142392955373084335320859663305248773674411336138752; |
In> Echo({ Hold(1+1), "=", 1+1 }); 1+1 = 2 Out> True; |
In> a := x; Out> x; In> x := 5; Out> 5; In> a; Out> x; In> Eval(a); Out> 5; |
Note that the behaviour would be different if we had exchanged the assignments. If the assignment a := x were given while x had the value 5, the variable a would also get the value 5 because the assignment operator := evaluates the right-hand side.
In particular, if "pred" immediately evaluates to False, the body is never executed. While is the fundamental looping construct on which all other loop commands are based. It is equivalent to the while command in the programming language C.
In> x := 0; Out> 0; In> While (x! < 10^6) [ Echo({x, x!}); x++; ]; 0 1 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 Out> True; |
The main difference with While is that Until always evaluates the body at least once, but While may not evaluate the body at all. Besides, the meaning of the predicate is reversed: While stops if "pred" is False while Until stops if "pred" is True.
The command Until(pred) body; is equivalent to pred; While(Not pred) body;. In fact, the implementation of Until is based on the internal command While. The Until command can be compared to the do ... while construct in the programming language C.
In> x := 0; Out> 0; In> Until (x! > 10^6) [ Echo({x, x!}); x++; ]; 0 1 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 Out> True; |
In> mysign(x) := If (IsPositiveReal(x), 1, -1); Out> True; In> mysign(Pi); Out> 1; In> mysign(-2.5); Out> -1; |
In> mysign(a); Out> -1; |
In> mysign(_x)_IsNumber(N(x)) <-- If (IsPositiveReal(x), 1, -1); Out> True; |
This command is not allowed in the body of the Secure command and will lead to an error.
In> Function("FirstOf", {list}) list[1]; Out> True; In> FirstOf({a,b,c}); Out> a; |
The purpose of this function is to make sure that the file will at least have been loaded, but is not loaded twice.
This command is most often used in a form like For(i=1, i<=10, i++) body, which evaluates body with i subsequently set to 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10.
The expression For(init, pred, incr) body is equivalent to init; While(pred) [body; incr;].
In> For (i:=1, i<=10, i++) Echo({i, i!}); 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 10 3628800 Out> True; |
In> ForEach(i,{2,3,5,7,11}) Echo({i, i!}); 2 2 3 6 5 120 7 5040 11 39916800 Out> True; |
An shorthand for Apply is provided by the @ operator.
In> Apply("+", {5,9}); Out> 14; In> Apply({{x,y}, x-y^2}, {Cos(a), Sin(a)}); Out> Cos(a)-Sin(a)^2; |
In> MapArgs(f(x,y,z),"Sin"); Out> f(Sin(x),Sin(y),Sin(z)); In> MapArgs({3,4,5,6}, {{x},x^2}); Out> {9,16,25,36}; |
In> Subst(x, Sin(y)) x^2+x+1; Out> Sin(y)^2+Sin(y)+1; In> Subst(a+b, x) a+b+c; Out> x+c; In> Subst(b+c, x) a+b+c; Out> a+b+c; |
The second calling sequence assigns the first element in the list of values to the first element in the list of variables, the second value to the second variable, etcetera.
In> WithValue(x, 3, x^2+y^2+1); Out> y^2+10; In> WithValue({x,y}, {3,2}, x^2+y^2+1); Out> 14; |
In> Sin(x)*Ln(a*b) Out> Sin(x)*Ln(a*b); In> % /: { Ln(_x*_y) <- Ln(x)+Ln(y) } Out> Sin(x)*(Ln(a)+Ln(b)); |
The forms the patterns can have are one of:
pattern <- replacement
{pattern,replacement}
{pattern,postpredicate,replacement}
Note that for these local rules, <- should be used in stead of <-- which defines a global rule.
The /: operator traverses an expression much like Subst does: top down, trying to apply the rules from the begin of the list of rules to the end of the list of rules. If the rules cannot be applied to a sub-expression, it will try the sub expressions of the expression being analyzed.
It might be necessary sometimes to use the /:: operator, which repeatedly applies the /: operator until the result doesn't change any more. Caution is required, since rules can contradict eachother, and that could result in an infinite loop. To detect this situation, just use /: repeatedly on the expression. The repetitive nature should become apparent.
In> Sin(u)*Ln(a*b) /: { Ln(_x*_y) <- Ln(x)+Ln(y) } Out> Sin(u)*(Ln(a)+Ln(b)); In> Sin(u)*Ln(a*b) /:: { a <- 2, b <- 3 } Out> Sin(u)*Ln(6); |
In> SetHelpBrowser("netscape") Out> "netscape"; In> ?? |
For each stack frame, it shows if the function evaluated was a built-in function or a user-defined function, and for the user-defined function, the number of the rule it is trying whether it was evaluating the pattern matcher of the rule, or the body code of the rule.
This functionality is not offered by default because it slows down the evaluation code.
In> f(x):=f(Sin(x)) Out> True; In> TraceStack(f(2)) Debug> 982 : f (Rule # 0 in body) Debug> 983 : f (Rule # 0 in body) Debug> 984 : f (Rule # 0 in body) Debug> 985 : f (Rule # 0 in body) Debug> 986 : f (Rule # 0 in body) Debug> 987 : f (Rule # 0 in body) Debug> 988 : f (Rule # 0 in body) Debug> 989 : f (Rule # 0 in body) Debug> 990 : f (Rule # 0 in body) Debug> 991 : f (Rule # 0 in body) Debug> 992 : f (Rule # 0 in body) Debug> 993 : f (Rule # 0 in body) Debug> 994 : f (Rule # 0 in body) Debug> 995 : f (User function) Debug> 996 : Sin (Rule # 0 in pattern) Debug> 997 : IsList (Internal function) Error on line 1 in file [CommandLine] Max evaluation stack depth reached. Please use MaxEvalDepth to increase the stack size as needed. |
Note that this command usually generates huge amounts of output. A more specific form of tracing (eg. TraceRule) is probably more useful for all but very simple expressions.
In> TraceExp(2+3); TrEnter(2+3); TrEnter(2); TrLeave(2, 2); TrEnter(3); TrLeave(3, 3); TrEnter(IsNumber(x)); TrEnter(x); TrLeave(x, 2); TrLeave(IsNumber(x),True); TrEnter(IsNumber(y)); TrEnter(y); TrLeave(y, 3); TrLeave(IsNumber(y),True); TrEnter(True); TrLeave(True, True); TrEnter(MathAdd(x,y)); TrEnter(x); TrLeave(x, 2); TrEnter(y); TrLeave(y, 3); TrLeave(MathAdd(x,y),5); TrLeave(2+3, 5); Out> 5; |
This is useful for tracing a function that is called from within another function. This way you can see how your function behaves in the environment it is used in.
In> TraceRule(x+y) 2+3*5+4; TrEnter(2+3*5+4); TrEnter(2+3*5); TrArg(2, 2); TrArg(3*5, 15); TrLeave(2+3*5, 17); TrArg(2+3*5, 17); TrArg(4, 4); TrLeave(2+3*5+4, 21); Out> 21; |
The word "numeric" in the previous paragraph has the following meaning. An expression is numeric if it is either a number (i.e. IsNumber returns True), or the quotient of two numbers, or an infinity (i.e. IsInfinity returns True).
In> 2 < 5; Out> True; In> Cos(1) < 5; Out> Cos(1)<5; In> N(Cos(1)) < 5; Out> True |
The word "numeric" in the previous paragraph has the following meaning. An expression is numeric if it is either a number (i.e. IsNumber returns True), or the quotient of two numbers, or an infinity (i.e. IsInfinity returns True).
In> 2 > 5; Out> False; In> Cos(1) > 5; Out> Cos(1)>5; In> N(Cos(1)) > 5; Out> False |
The word "numeric" in the previous paragraph has the following meaning. An expression is numeric if it is either a number (i.e. IsNumber returns True), or the quotient of two numbers, or an infinity (i.e. IsInfinity returns True).
In> 2 <= 5; Out> True; In> Cos(1) <= 5; Out> Cos(1)<=5; In> N(Cos(1)) <= 5; Out> True |
The word "numeric" in the previous paragraph has the following meaning. An expression is numeric if it is either a number (i.e. IsNumber returns True), or the quotient of two numbers, or an infinity (i.e. IsInfinity returns True).
In> 2 >= 5; Out> False; In> Cos(1) >= 5; Out> Cos(1)>=5; In> N(Cos(1)) >= 5; Out> False |
The expression e1 != e2 is equivalent to Not(e1 = e2).
In> 1 != 2; Out> True; In> 1 != 1; Out> False; |
Note that the test is on syntactic equality, not mathematical equality. Hence even if the result is False, the expressions can still be (mathematically) equal; see the examples underneath. Put otherwise, this function tests whether the two expressions would be displayed in the same way if they were printed.
In> e1 := (x+1) * (x-1); Out> (x+1)*(x-1); In> e2 := x^2 - 1; Out> x^2-1; In> e1 = e2; Out> False; In> Expand(e1) = e2; Out> True; |
In> Not True Out> False; In> Not False Out> True; In> Not(a) Out> Not a; |
In> True And False Out> False; In> And(True,True) Out> True; In> False And a Out> False; In> True And a Out> And(a); In> And(True,a,True,b) Out> b And a; |
In> True Or False Out> True; In> False Or a Out> Or(a); In> Or(False,a,b,True) Out> True; |
The second form test whether the expression depends on any of the variables named in the list. The result is True if none of the variables appear in the expression and False otherwise.
In> IsFreeOf(Sin(x), x); Out> False; In> IsFreeOf(Sin(x), y); Out> True; In> IsFreeOf(D(x) a*x+b, x); Out> True; In> IsFreeOf(Sin(x), {x,y}); Out> False; |
In> IsZeroVector({0, x, 0}); Out> False; In> IsZeroVector({x-x, 1 - D(x) x}); Out> True; |
In> IsEven(4); Out> True; In> IsEven(-1); Out> False; |
In> IsOdd(4); Out> False; In> IsOdd(-1); Out> True; |
In> IsFunction(x+5); Out> True; In> IsFunction(x); Out> False; |
In> IsAtom(x+5); Out> Falso; In> IsAtom(5); Out> True; |
In> IsString("duh"); Out> True; In> IsString(duh); Out> False; |
In> IsNumber(6); Out> True; In> IsNumber(3.25); Out> True; In> IsNumber(I); Out> False; In> IsNumber("duh"); Out> False; |
In> IsList({2,3,5}); Out> True; In> IsList(2+3+5); Out> False; |
In> IsBound(x); Out> False; In> x := 5; Out> 5; In> IsBound(x); Out> True; |
In> IsBoolean(a) Out> False; In> IsBoolean(True) Out> True; In> IsBoolean(a And b) Out> True; |
In> IsNegativeNumber(6); Out> False; In> IsNegativeNumber(-2.5); Out> True; |
In> IsNegativeInteger(31); Out> False; In> IsNegativeInteger(-2); Out> True; |
In> IsPositiveNumber(6); Out> True; In> IsPositiveNumber(-2.5); Out> False; |
In> IsPositiveInteger(31); Out> True; In> IsPositiveInteger(-2); Out> False; |
In> IsNotZero(3.25); Out> True; In> IsNotZero(0); Out> False; |
In> IsNonZeroInteger(0) Out> False; In> IsNonZeroInteger(-2) Out> True; |
In> IsInfinity(10^1000); Out> False; In> IsInfinity(-Infinity); Out> True; |
In> IsPositiveReal(Sin(1)-3/4); Out> True; In> IsPositiveReal(Sin(1)-6/7); Out> False; In> IsPositiveReal(Exp(x)); Out> False; |
In> IsNegativeReal(Sin(1)-3/4); Out> False; In> IsNegativeReal(Sin(1)-6/7); Out> True; In> IsNegativeReal(Exp(x)); Out> False; |
In> IsConstant(Cos(x)) Out> False; In> IsConstant(Cos(2)) Out> True; In> IsConstant(Cos(2+x)) Out> False; |
Not negation, read as 'not'
( (a=>b) And (b=>c) ) => (a=>c) |
In> CanProve(( (a=>b) And (b=>c) ) => (a=>c)) Out> True; |
Not ( Not x) --> x eliminate double negation x=>y --> Not x Or y eliminate implication Not (x And y) --> Not x Or Not y De Morgan's law Not (x Or y) --> Not x And Not y De Morgan's law (x And y) Or z --> (x Or z) And (y Or z) Distribution x Or (y And z) --> (x Or y) And (x Or z) Distribution |
(p1 Or p2 Or ...) And (q1 Or q2 Or ...) And ... |
(p Or Y) And ( Not p Or Z) --> (Y Or Z) |
As a last step, the algorithm negates the result again. This has the added advantage of simplifying the expression further.
In> CanProve(a Or Not a) Out> True; In> CanProve(True Or a) Out> True; In> CanProve(False Or a) Out> a; In> CanProve(a And Not a) Out> False; In> CanProve(a Or b Or (a And b)) Out> a Or b; |
Typical examples are Simplify(%) and PrettyForm(%)to simplify and show the result in a nice form respectively.
In> Taylor(x,0,5)Sin(x) Out> x-x^3/6+x^5/120; In> PrettyForm(%) 3 5 x x x - -- + --- 6 120 |
Note that for most analytic functions Yacas understands Infinity. Thus Infinity*2 will return Infinity, and a < Infinity will evaluate to True.
In> 2*Infinity Out> Infinity; In> 2 |
In> Sin(3*Pi/2) Out> -1; In> Pi Out> Pi; In> N(Pi) Out> 3.1415926535; |
In> 2*Infinity Out> Infinity; In> 0*Infinity Out> Undefined; |
The first form is the most basic one. It evaluates the expression on the right-hand side and assigns it to the variable named on the left-hand side. The left-hand side is not evaluated. The evaluated expression is also returned.
The second form is a small extension, which allows one to do multiple assignments. The first entry in the list on the right-hand side is assigned to the first variable mentionedon the left-hand side, the second entry on the right-hand side to the second variable on the left-hand side, etcetera. The list on the right-hand side must have at least as many entries as the list on the left-hand side. Any excess entries are silently ignored. The result of the expression is the list of values that have been assigned.
The third form allows one to change an entry in the list. If the index "i" is an integer, the "i"-th entry in the list is changed to the expression on the right-hand side. It is assumed that the length of the list is at least "i". If the index "i" is a string, then "var" is considered to be an associative list (sometimes called hash table), and the key "i" is paired with the value "exp". In both cases, the right-hand side is evaluated before the assigment and the result of the assignment is True.
The last form defines a function. For example, the assignment f(x) := x^2 removes all rules associated with f(x) and defines the rule f(_x) <-- x^2. Note that the left-hand side may take a different form if "f" is defined to be a prefix, infix or bodied function. This case is a bit special since the right-hand side is not evaluated immediately, but only if the function "f" is used. If this takes time, it may be better to force an immediate evaluation with Eval (see the last example).
In> a := Sin(x) + 3; Out> Sin(x)+3; In> a; Out> Sin(x)+3; |
Multiple assignments:
In> {a,b,c} := {1,2,3}; Out> {1,2,3}; In> a; Out> 1; In> b+c; Out> 5; |
Assignment to a list:
In> xs := { 1,2,3,4,5 }; Out> {1,2,3,4,5}; In> xs[3] := 15; Out> True; In> xs; Out> {1,2,15,4,5}; |
Building an associative list:
In> alist := {}; Out> {}; In> alist["cherry"] := "red"; Out> True; In> alist["banana"] := "yellow"; Out> True; In> alist["cherry"]; Out> "red"; In> alist; Out> {{"banana","yellow"},{"cherry","red"}}; |
Defining a function:
In> f(x) := x^2; Out> True; In> f(3); Out> 9; In> f(Sin(a)); Out> Sin(a)^2; In> Infix("*&*",10); Out> True; In> x1 *&* x2 := x1/x2 + x2/x1; Out> True; In> Sin(a) *&* Cos(a); Out> Tan(1)+Cos(1)/Sin(1); In> Clear(a); Out> True; In> Sin(a) *&* Exp(a); Out> Sin(a)/Exp(a)+Exp(a)/Sin(a); |
In the following example, it may take some time to compute the Taylor expansion. This has to be done every time the function f is called.
In> f(a) := Taylor(x,0,25) Sin(x); Out> True; In> f(1); Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-x^11/39916800+x^13/6227020800-x^15/1307 674368000+x^17/355687428096000-x^19/121645100408832000+x^21/51090942171709440000 -x^23/25852016738884976640000+x^25/15511210043330985984000000; In> f(2); Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-x^11/39916800+x^13/6227020800-x^15/1307 674368000+x^17/355687428096000-x^19/121645100408832000+x^21/51090942171709440000 -x^23/25852016738884976640000+x^25/15511210043330985984000000; |
In> f(a) := Eval(Taylor(x,0,25) Sin(x)); Out> True; In> f(1); Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-x^11/39916800+x^13/6227020800-x^15/1307 674368000+x^17/355687428096000-x^19/121645100408832000+x^21/51090942171709440000 -x^23/25852016738884976640000+x^25/15511210043330985984000000; In> f(2); Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880-x^11/39916800+x^13/6227020800-x^15/1307 674368000+x^17/355687428096000-x^19/121645100408832000+x^21/51090942171709440000 -x^23/25852016738884976640000+x^25/15511210043330985984000000; |
The statement Set(var, exp) is equivalent to var := exp, but the := operator has more uses like changing individual entries in a list.
In> Set(a, Sin(x)+3); Out> True; In> a; Out> Sin(x)+3; |
In> a := 5; Out> 5; In> a^2; Out> 25; In> Clear(a); Out> True; In> a^2; Out> a^2; |
By default, all variables in Yacas are global. This means that the variable has the same value everywhere. But sometimes it is useful to have a private copy of some variable, either to prevent the outside world from changing it or to prevent accidental changes to the outside world. This can be achieved by declaring the variable local. Now only expressions within the Prog block (or its syntactic equivalent, the [ ] block) can access and change it. Functions called within this block cannot access the local copy unless this is specifically allowed with UnFence.
In> a := 3; Out> 3; In> [ a := 4; a; ]; Out> 4; In> a; Out> 4; In> [ Local(a); a := 5; a; ]; Out> 5; In> a; Out> 4; |
In> x := 5; Out> 5; In> x++; Out> True; In> x; Out> 6; |
In> x := 5; Out> 5; In> x--; Out> True; In> x; Out> 4; |
In> a := Object("IsNumber", x); Out> Object("IsNumber",x); In> Eval(a); Out> Object("IsNumber",x); In> x := 5; Out> 5; In> Eval(a); Out> 5; |
Places where this is used include the global variables % and I.
The use of lazy in the name stems from the concept of lazy evaluation. The object the global variable is bound to will only be evaluated when called. The LazyGlobal property only holds once: after that, the result of evaluation is stored in the global variable, and it won't be reevaluated again:
In> a:=Hold(Taylor(x,0,30)Sin(x)) Out> Taylor(x,0,30)Sin(x); In> LazyGlobal(a) |
In> a:=Hold(2+3) Out> 2+3; In> a Out> 2+3; In> LazyGlobal(a) Out> True; In> a Out> 5; |
In> UniqueConstant() Out> C9 In> UniqueConstant() Out> C10 |
In> FullForm(a+b+c); (+ (+ a b )c ) Out> a+b+c; In> FullForm(2*I*b^2); (* (Complex 0 2 )(^ b 2 )) Out> Complex(0,2)*b^2; |
If the second calling sequence is used, Echo will print all the entries in the list subsequently to the current output, followed by a newline. Any strings in the list are printed without quotation marks. All other entries are followed by a space.
Echo always returns True.
In> Echo(5+3); 8 Out> True; In> Echo({"The square of two is ", 2*2}); The square of two is 4 Out> True; |
Note that one must use the second calling sequence if one wishes to print a list:
In> Echo({a,b,c}); a b c Out> True; In> Echo({{a,b,c}}); {a,b,c} Out> True; |
In> Taylor(x,0,9)Sin(x) Out> x-x^3/6+x^5/120-x^7/5040+x^9/362880; In> PrettyForm(%) 3 5 7 9 x x x x x - -- + --- - ---- + ------ 6 120 5040 362880 Out> True; |
In> EvalFormula(Taylor(x,0,7)Sin(x)) 3 5 7 x x x Taylor( x , 0 , 7 , Sin( x ) ) = x - -- + --- - ---- 6 120 5040 Out> True |
In> Write(1); 1Out> True; In> Write(1,2); 1 2Out> True; |
In> Write("Hello, world!"); "Hello, world!"Out> True; In> WriteString("Hello, world!"); Hello, world!Out> True; |
In> Space(5); Out> True; |
In> NewLine(); Out> True; |
2 + 5; |
Then we can have the following dialogue:
In> FromFile("foo") res := Read(); Out> 2+5; In> FromFile("foo") res := ReadToken(); Out> 2; |
In> FromString("2+5; this is never read") res := Read(); Out> 2+5; In> FromString("2+5; this is never read") res := Eval(Read()); Out> 7; |
In> [ Echo("Result:"); PrettyForm(Taylor(x,0,9) Sin(x)); ]; Result: 3 5 7 9 x x x x x - -- + --- - ---- + ------ 6 120 5040 362880 Out> True; |
Now suppose one wants to send the output of this command to a file. This can be achieved as follows:
In> ToFile("out") [ Echo("Result:"); PrettyForm(Taylor(x,0,9) Sin(x)); ]; Out> True; |
After this command the file out contains:
Result: 3 5 7 9 x x x x x - -- + --- - ---- + ------ 6 120 5040 362880 |
In> str := ToString() \ In> [ WriteString("The square of 8 is "); Write(8^2); ]; Out> "The square of 8 is 64"; |
In> FromString("2+5;") Read(); Out> 2+5; In> FromString("") Read(); Out> EndOfFile; |
The expression a+b is written in LISP syntax as (+ a b). The advantage of this syntax is that it is less ambiguous than the infix operator grammar that Yacas uses by default.
In> FromString("(+ a b)") LispRead(); Out> a+b; In> FromString("(List (Sin x) (- (Cos x)))") LispRead(); Out> {Sin(x),-Cos(x)}; |
A token is for computer languages what a word is for human languages: it is the smallest unit in which a command can be divided, so that the semantics (that is the meaning) of the command is in some sense a combination of the semantics of the tokens. Hence a := foo consists of three tokens, namely a, :=, and foo.
In> FromString("a := Sin(x)") \ In> While((tok := ReadToken()) != EndOfFile) Echo(tok); a := Sin ( x ) Out> True; |
The purpose of this function is to make sure that the file will at least have been loaded, but is not loaded twice.
This is similar to the way php works. You can have a static text file with dynamic content generated by Yacas.
Note that the second letter in the name of this command is a lower case L (from "line").
In> WriteString("First line" : Nl() : "Second line" : Nl()); First line Second line Out> True; |
In> SetStringMid(3,"XY","abcdef") Out> "abXYef"; |
In> StringMid(3,2,"abcdef") Out> "cd"; In> "abcdefg"[2 .. 4] Out> "bcd"; |
String is the inverse of Atom: turns atom into "atom".
In> String(a) Out> "a"; In> Atom("a") Out> a; |
In> ConcatStrings("a","b","c") Out> "abc"; |
This is useful in cases where a guaranteed free variable is needed, like in the macro-like functions (For, While, etc.).
In> LocalSymbols(a,b)a+b Out> $a6+ $b6; |
In> PatchString("Two plus three is <? Write(2+3); ?> "); Out> "Two plus three is 5 "; |
The plugin feature is currently in an experimental stage. There are some examples in the plugins/ directory. These are not built by default because they cannot be guaranteed to compile on every platform (yet). The plugins need to be compiled after Yacas itself has been compiled and installed successfully. The plugins/ directory contains a README file with more details on compilation.
In addition to the plugin structure in the Yacas engine, there is a 'cstubgen' module (currently still in development) that allows rapid scripting of a plugin. Essentially all that is required is to write a file that looks like the header file of the original library, but written in Yacas syntax. the 'cstubgen' module is then able to write out a c++ file that can be compiled and linked with the original library, and then loaded from within Yacas. Including a function in the plugin will typically take just one line of Yacas code. There are a few examples in the plugins/ directory (the files ending with api.stub). The make file makefile.plugin is configured to automatically convert these to the required c++ files.
In addition to the c++ stub file cstubgen also automatically generates some documentation on the functions included in the stub. This documentation is put in a file with extension 'description'.
The plugin facility is not supported for each platform yet. Specifically, it is only supported on platforms that support the elf binary format. (loading DLLs is platform-dependent).
This chapter assumes the reader is comfortable programming in c++.
In> DllLoad("./libopengl.so"); Out> True; |
Return type, function name, and list of arguments should be literal strings (surrounded by quotes).
If fname2 is not supplied, it will be assumed to be the same as fname.
The return types currently supported are "int", "double" and "void". The argument values that are currently supported are "int", "double", and "input_string". Argument types can be specified simply as a string referring to their type, like "int", or they can be lists with an additional element stating the name of the variable: {"int","n"}. The variable will then show up in the automatically generated documentation as having the name n.
StubApiCFunction("void","glVertex3d",{"double","double","double"}); |
There needs to ba a function in the plugin somewhere of the form
static LispEnvironment* env = NULL; void GlutSetEnv(LispEnvironment& aEnv) { env = &aEnv; } |
StubApiCSetEnv("GlutSetEnv"); |
By default the struct will be deleted from memory with a normal call to free(...). This can be overriden with a function given as second argument, freefunction. This is needed in the case where there are additional operations that need to be performed in order to delete the object from memory.
typedef struct SomeStruct { int a; int b; } SomeStruct; |
StubApiCStruct("SomeStruct*") |