Yacas first tries to load a file from the current directory, and otherwise it tries to load from directories defined with this function, in the order they are defined. Note there will be at least one directory specified at start-up time, defined during compilation. This is the directory Yacas searches for the initialization scripts and standard scripts.
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 |
These operators are implemented in the standard math library (as opposed to being built-in). This means that they can be extended by the user.
In> 2+3 Out> 5; In> 2*3 Out> 6; |
If Div(x,y) returns "a" and Mod(x,y) equals "b", then these numbers satisfy x = a*y + b and 0 <= b < y.
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) |
If the second calling form is used, Gcd will return the greatest common divisor of all the integers or polynomials in "list". It uses the identity
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; |
In> 1 << 10 Out> 1024; In> -1024 >> 10 Out> -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> GetPrecision(); Out> 10; In> Precision(20); Out> True; In> GetPrecision(); Out> 20; |
Application of the N operator will make Yacas calculate floating point representations of functions whenever possible. 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> {1.2,3.123,4.5} Out> {1.2,3.123,4.5}; In> Rationalize(%) Out> {6/5,3123/1000,9/2}; |
This function essentially checks for all integers between 2 and the square root of "n" whether they divide "n", and hence may take a long time for large numbers.
In> IsPrime(1) Out> False; In> IsPrime(2) Out> True; In> IsPrime(10) Out> False; In> IsPrime(23) Out> True; In> Select("IsPrime", 1 .. 100) Out> {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; |
This function essentially checks for all integers between 2 and the square root of "n" for the largest divisor, and then tests whether "n" is a power of this divisor. So it will take a long time for large numbers.
In> IsPrimePower(9) Out> True; In> IsPrimePower(10) Out> False; In> Select("IsPrimePower", 1 .. 50) Out> {2,3,4,5,7,8,9,11,13,16,17,19,23,25,27,29,31,32,37,41,43,47,49}; |
The factorization is returned as a list of pairs. The first member of each pair is the factor, while the second member denotes the power to which this factor should be raised. So the factorization "x = p1^n1 * ... * p9^n9" is returned as {{p1,n1}, ..., {p9,n9}}.
In> Factors(24); Out> {{2,3},{3,1}}; In> Factors(2*x^3 + 3*x^2 - 1); Out> {{2,1},{x+1,2},{x-1/2,1}}; |
In> PrettyForm(Factor(24)); 3 2 * 3 Out> True; In> PrettyForm(Factor(2*x^3 + 3*x^2 - 1)); 2 / 1 \ 2 * ( x + 1 ) * | x - - | \ 2 / Out> True; |
In> PrettyForm(PAdicExpand(1234, 10)); 2 3 3 * 10 + 2 * 10 + 10 + 4 Out> True; In> PrettyForm(PAdicExpand(x^3, x-1)); 2 3 3 * ( x - 1 ) + 3 * ( x - 1 ) + ( x - 1 ) + 1 Out> True; |
This is especially useful for polynomials, since series expansions that converge slowly will typically converge a lot faster if calculated using a continued fraction expansion.
In> PrettyForm(ContFrac(N(Pi))) 1 --------------------------- + 3 1 ----------------------- + 7 1 ------------------ + 15 1 -------------- + 1 1 -------- + 292 rest + 1 Out> True; In> PrettyForm(ContFrac(x^2+x+1, 3)) x ---------------- + 1 x 1 - ------------ x -------- + 1 rest + 1 Out> True; |
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; |
The numbers in "xlist" must evaluate to floating point numbers if the N operator is applied on them.
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 multiples of Pi/6 or Pi/4.
These functions are threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> Sin(1) Out> Sin(1); In> N(Sin(1),20) Out> 0.84147098480789650665; In> Sin(Pi/4) Out> Sqrt(2)/2; |
Note that the number "y" is not unique. For instance, "Sin(0)" and "Sin(Pi)" both equal 0, so what should "ArcSin(0)" be? In Yacas, it is agreed that the value of "ArcSin(x)" should be in the interval [-Pi/2,Pi/2]. The same goes for "ArcTan(x)". However, "ArcCos(x)" is in the interval [0,Pi].
Usually, Yacas leaves these functions alone unless it is forced to do a numerical evaluation by the N function. If the argument is -1. 0, or 1 however, Yacas will simplify the expression. If the argument is complex, the expression will be rewritten as a Ln function.
These functions are threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> ArcSin(1) Out> Pi/2; In> ArcSin(1/3) Out> ArcSin(1/3); In> Sin(ArcSin(1/3)) Out> 1/3; In> N(ArcSin(0.75)) Out> 0.848062; In> N(Sin(%)) Out> 0.7499999477; |
This function is threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> Exp(0) Out> 1; In> Exp(I*Pi) Out> -1; In> N(Exp(1)) Out> 2.7182818284; |
This function is threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> Ln(1) Out> 0; In> Ln(Exp(x)) Out> x; In> D(x) Ln(x) Out> 1/x; |
This function is threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> Sqrt(16) Out> 4; In> Sqrt(15) Out> Sqrt(15); In> N(Sqrt(15)) Out> 3.8729833462; In> Sqrt(4/9) Out> 2/3; In> Sqrt(-1) Out> Complex(0,1); |
This function is connected to the Sign function by the identity "Abs(x) * Sign(x) = x" for real "x".
This function is threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> Abs(2); Out> 2; In> Abs(-1/2); Out> -1/2; In> Abs(3+4*I); Out> 5; |
This function is connected to the Abs function by the identity "Abs(x) * Sign(x) = x" for real "x".
This function is threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> Sign(2) Out> 1; In> Sign(-3) Out> -1; In> Sign(0) Out> 1; In> Sign(-3) * Abs(-3) Out> -3; |
Note that, at the moment, many functions in Yacas assume that all numbers are real unless it is obvious that it is a complex number. Hence Im(Sqrt(x)) evaluates to 0 which is only true for nonnegative "x".
In> I Out> Complex(0,1); In> 3+4*I Out> Complex(3,4); In> Complex(-2,0) Out> -2; |
In> Re(5) Out> 5; In> Re(I) Out> 0; In> Re(Complex(3,4)) Out> 3; |
In> Im(5) Out> 0; In> Im(I) Out> 1; In> Im(Complex(3,4)) Out> 4; |
In> I Out> Complex(0,1); In> I = Sqrt(-1) Out> True; |
In> Conjugate(2) Out> 2; In> Conjugate(Complex(a,b)) Out> Complex(a,-b); |
In> Arg(2) Out> 0; In> Arg(-1) Out> Pi; In> Arg(1+I) Out> Pi/4; |
This function is threaded, meaning that if the argument "x" is a list, the function is applied to all the entries in the list.
In> 5! Out> 120; In> 1 * 2 * 3 * 4 * 5 Out> 120; In> (1/2)! Out> Sqrt(Pi)/2; |
In> Bin(10, 4) Out> 210; In> 10! / (4! * 6!) Out> 210; |
If the second calling sequence is used, the expression "body" is evaluated while the variable "var" ranges over all integers from "from" upto "to", and the sum of all the results is returned. Obviously, "to" should be greater than or equal to "from".
In> Sum({1,4,9}); Out> 14; In> Sum(i, 1, 3, i^2); Out> 14; |
In> Average({1,2,3,4,5}); Out> 3; In> Average({2,6,7}); Out> 5; |
If the second calling sequence is used, the expression "body" is evaluated while the variable "var" ranges over all integers from "from" upto "to", and the product of all the results is returned. Obviously, "to" should be greater than or equal to "from".
In> Factorize({1,2,3,4}); Out> 24; In> Factorize(i, 1, 4, i); Out> 24; |
In> Min(2,3); Out> 2; In> Min({5,8,4}); Out> 4; |
In> Max(2,3); Out> 3; In> Max({5,8,4}); Out> 8; |
In> IsZero(3.25) Out> False; In> IsZero(0) Out> True; In> IsZero(x) Out> False; |
In> IsRational(5) Out> False; In> IsRational(2/7) Out> True; In> IsRational(a/b) Out> True; In> IsRational(x + 1/x) Out> False; |
In> Numer(2/7) Out> 2; In> Numer(a / x^2) Out> a; In> Numer(5) Out> 5; |
In> Denom(2/7) Out> 7; In> Denom(a / x^2) Out> x^2; In> Denom(5) Out> 1; |
In> Commutator(2,3) Out> 0; In> PrettyPrinter("PrettyForm"); True Out> In> A := { {0,x}, {0,0} } / \ | ( 0 ) ( x ) | | | | ( 0 ) ( 0 ) | \ / Out> In> B := { {y,0}, {0,z} } / \ | ( y ) ( 0 ) | | | | ( 0 ) ( z ) | \ / Out> In> Commutator(A,B) / \ | ( 0 ) ( x * z - y * x ) | | | | ( 0 ) ( 0 ) | \ / Out> |
In> PrettyForm(Taylor(x,0,9) Sin(x)) 3 5 7 9 x x x x x - -- + --- - ---- + ------ 6 120 5040 362880 Out> True; |
In> PrettyPrinter("PrettyForm") True 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,7) 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 the inverse of a function "f": if we take "g(var)=var", then "h(f(var))=var" (upto order "degree"), 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; |
The function will iterate using Newton's method until it estimates that it has come within a distance "accuracy" of the correct solution, and then it will return its best guess. In particular, it may loop forever if the algorithm does not converge.
In> Newton(Sin(x),x,3,0.0001) Out> 3.1415926535; |
The D operator is threaded in both "var" and "expr". This means that if either of them is a list, the function is applied to each entry in the list. The results are collected in another list which is returned. If both "var" and "expr" are a list, their lengths should be equal. In this case, the first entry in the list "expr" is differentiated with respect to the first entry in the list "var", the second entry in "expr" is differentiated with respect to the second entry in "var", and so on.
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)}; |
Curl(f,x) = { D(x[2]) f[3] - D(x[3]) f[2], D(x[3]) f[1] - D(x[1]) f[3], D(x[1]) f[2] - D(x[2]) f[1] }
Both "vector" and "basis" should be lists of length 3.
In> Curl({x*y,x*y,x*y},{x,y,z}) Out> {x,-y,y-x}; |
Diverge(f,x) = D(x[1]) f[1] + ... + D(x[n]) f[n],
where n is the length of the lists "vector" and "basis". These lists should have equal length.
In> Diverge({x*y,x*y,x*y},{x,y,z}) Out> y+x; |
Some simple integration rules have currently been implemented. Polynomials, quotients of polynomials, the transcendental functions Sin, Cos, Exp, and Ln, and products of these functions with polynomials can all be integrated.
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; |
It does this by trying all possible combinations for "e1", "e2", etcetera. Every possibility is numerically evaluated using N and compared with the numerical evaluation of "expr". If the approximations are equal (upto a certain margin), this possibility is returned. Otherwise, the expression is returned unevaluated.
Note that due to the use of numerical approximations, there is a small chance that the expression returned by RadSimp is close but not equal to "expr". The last example underneath illustrates this problem. Furthermore, if the numerical value of "expr" is large, the number of possibilities becomes exorbitantly big so the evaluation may take very long.
In> RadSimp(Sqrt(9+4*Sqrt(2))) Out> Sqrt(8)+1; 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> Sqrt(2)+3; |
But this command may yield incorrect results:
In> RadSimp(Sqrt(1+10^(-6))) Out> 1; |
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> {1.2,3.123,4.5} Out> {1.2,3.123,4.5}; In> Rationalize(%) Out> {6/5,3123/1000,9/2}; |
The first calling sequence solves the equation "eq" for the variable "var". Use the == operator to form the equation. The value of "var" which satisfies the equation, is returned. Note that only one solution is found and returned.
To solve a system of equations, the second form should be used. It solves the system of equations contained in the list "eqlist" for the variables appearing in the list "varlist". A list of results is returned, and each result is a list containing the values of the variables in "varlist". Again, at most a single solution is returned.
The task of solving a single equation is simply delegated to SuchThat. Multiple equations are solved recursively: firstly, an equation is sought in which one of the variables occurs exactly once; then this equation is solved with SuchThat; and finally the solution is substituted in the other equations by Eliminate decreasing the number of equations by one. This suffices for all linear equations and a large group of simple nonlinear equations.
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}}; |
An example which Solve cannot solve:
In> Solve({x^2-x == y^2-y, x^2-x == y^3+y}, {x,y}); Out> {}; |
Basically, only expressions in which "var" occurs only once are handled; and in fact, SuchThat may even give wrong results if the variables occurs more than once. This is a consequence of the implementation, which repeatedly applies the inverse of the top function until the variable "var" is reached.
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> (a+b)*x+c; In> SuchThat(%, x) Out> (-c)/(a+b); |
In> Subst(Cos(b), c) (Sin(a)+Cos(b)^2/c) Out> Sin(a)+c^2/c; In> Eliminate(Cos(b), c, Sin(a)+Cos(b)^2/c) Out> Sin(a)+c; |
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}; |
The second calling sequence is used for unidirectional limits. If one gives "dir" the value Left, the limit is taken as "var" approaches "val" from the positive infinity; and Right will take the limit from the negative 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; |
This function is used in for instance Integrate, to bring down the expression into a simpler form that hopefully can be integrated easily.
In> PrettyPrinter("PrettyForm"); True Out> 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> |
The lists "xlist" and "ylist" should be of equal length. Furthermore, the entries of "xlist" should be all distinct to ensure that there is one and only one solution.
This routine uses the Lagrange interpolant formula to build up the polynomial.
In> f := LagrangeInterpolant({0,1,2}, {0,1,1}, x); Out> (x*(x-1))/2-x*(x-2); In> Eval(Subst(x,0) f); Out> 0; In> Eval(Subst(x,1) f); Out> 1; In> Eval(Subst(x,2) f); Out> 1; In> PrettyPrinter("PrettyForm"); True Out> 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> |
The Fibonacci sequence is 1, 1, 2, 3, 5, 8, 13, 21, ..., where every number is the sum of the two preceding numbers. Formally, it is defined by F(1) = 1, F(2) = 1, and F(n+1) = F(n) + F(n-1), where F(n) denotes the n-th Fibonacci number.
In> Fibonacci(4) Out> 3; In> Fibonacci(8) Out> 21; In> Table(Fibonacci(i), i, 1, 10, 1) Out> {1,1,2,3,5,8,13,21,34,55}; |
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; |
The Jacobi polynomials are orthogonal with respect to the weight function (1-x)^a (1+x)^b on the interval [-1,1]. They satisfy the recurrence relations:
P(0,a,b,x) = 1 a - b / a + b \ P(1,a,b,x) = ----- + x | 1 + ----- | 2 \ 2 / 2 2 a - b + x (2n+a+b-2) (n+a+b) P(n,a,b,x) = (2n + a + b - 1) * ---------------------------- P(n-1,a,b,x) 2n (2n+a+b-2) (n+a+b) (n+a-1) (n+b-1) (2n+a+b) - ------------------------ P(n-2,a,b,x), for n > 1. n (n+a+b) (2n+a+b-2) |
Legendre polynomials are a special case of Jacobi polynomials with the specific parameter values a = b = 0. So they form an orthogonal system with respect to the weight function identically equal to 1 on the interval [-1,1], and they satisfy the recurrence relations:
P(0,x) = 1 P(1,x) = x (2n - 1) x n - 1 P(n,x) = ---------- P(n-1,x) - ----- P(n-2,x), for n > 1. 2n n |
Most of the work is performed by the internal function OrthoPoly.
In> PrettyPrinter("PrettyForm"); True Out> In> OrthoP(3, x); / 2 \ | 5 * x 3 | x * | ------ - - | \ 2 2 / Out> In> OrthoP(3, 1, 2, x); 1 / / 21 * x 7 \ 7 \ - + x * | x * | ------ - - | - - | 2 \ \ 2 2 / 2 / Out> In> Expand(%) 3 2 21 * x - 7 * x - 7 * x + 1 ---------------------------- 2 Out> In> OrthoP(3, 1, 2, 0.5); -0.8124999999 Out> |
The Hermite polynomials are orthogonal with respect to the weight function e^(-x^2/2) on the entire real axis. They satisfy the recurrence relations:
H(0,x) = 1 H(1,x) = 2x H(n,x) = 2x H(n-1,x) - 2(n-1) H(n-2,x), for n > 1. |
Most of the work is performed by the internal function OrthoPoly.
In> OrthoH(3, x); Out> x*(8*x^2-12); In> OrthoH(6, 0.5); Out> 31; |
The Gegenbauer polynomials are orthogonal with respect to the weight function (1-x^2)^(a-1/2) on the interval [-1,1]. Hence they are connected to the Jacobi polynomials via G(n, a, x) = P(n, a-1/2, a-1/2, x). They satisfy the recurrence relations:
G(0,a,x) = 1 G(1,a,x) = 2x / a - 1 \ / 2 (a-2) \ G(n,a,x) = 2 | 1 + ----- | x G(n-1,a,x) - | 1 + ------- | G(n-2,a,x), for n>1. \ n / \ n / |
Most of the work is performed by the internal function OrthoPoly.
In> OrthoG(5, 1, x); Out> x*((32*x^2-32)*x^2+6); In> OrthoG(5, 2, -0.5); Out> 2; |
The Laguerre polynomials are orthogonal with respect to the weight function x^a * e^(-x) on the positive real axis. They satisfy the recurrence relations:
L(0,a,x) = 1 L(1,a,x) = a + 1 - x / a - 1 - x \ / a - 1 \ L(n,a,x) = | 2 + --------- | L(n-1,a,x) - | 1 + ----- | L(n-2,a,x), for n>1. \ n / \ n / |
Most of the work is performed by the internal function OrthoPoly.
In> OrthoL(3, 1, x); Out> x*(x*(2-x/6)-6)+4; In> OrthoL(3, 1/2, 0.25); Out> 1.2005208334; |
The Tschebyscheff polynomials of the first kind are orthogonal with respect to the weight function (1-x^2)^(-1/2). Hence they are a special case of the Gegenbauer polynomials, with a=0. They satisfy the recurrence relations:
T(0,x) = 1 T(1,x) = x T(n,x) = 2x T(n-1,x) - T(n-2,x), for n > 1. |
Most of the work is performed by the internal function OrthoPoly.
IIn> OrthoT(3, x); Out> x*(4*x^2-3); In> OrthoT(10, 0.9); Out> -0.2007474688; |
The Tschebyscheff polynomials of the second kind are orthogonal with respect to the weight function (1-x^2)^(1/2). Hence they are a special case of the Gegenbauer polynomials, with a=1. They satisfy the recurrence relations:
U(0,x) = 1 U(1,x) = 2x U(n,x) = 2x U(n-1,x) - u(n-2,x), for n > 1. |
Most of the work is performed by the internal function OrthoPoly.
In> OrthoU(3, x); Out> x*(8*x^2-4); In> OrthoU(10, 0.9); Out> -2.2234571776; |
The list of coefficients starts with the lowest order, so that for example
OrthoLSum(c, a, x) = c[1] L_0(a,x) + c[2] L_1(a,x) + ... + c[N] L_{N-1}(a,x). |
Most of the work is performed by the internal function OrthoPolySum. The individual polynomials entering the series are not computed, only the sum of the series.
In> Expand(OrthoPSum({1,0,0,1/7,1/8}, 3/2, 2/3, x)); Out> (7068985*x^4)/3981312+(1648577*x^3)/995328+(-3502049*x^2)/4644864+(-4372969*x)/6967296+28292143/27869184; |
All known families are stored in the association list KnownOrthoPoly. The name serves as key. At the moment the following names are known to Yacas: "Jacobi", "Gegenbauer", "Laguerre", "Hermite", "Tscheb1", and "Tscheb2". The value associated to the key is a pure function that takes two arguments: the order "n" and the extra parameters "p", and returns a list of two lists: the first list contains the coefficients {A,B} of the n=1 polynomial, i.e. "A+B*x"; the second list contains the coefficients {A,B,C} in the recurrence relation, i.e. "P_n = (A+B*x)*P_{n-1}+C*P_{n-2}". (There are only 3 coefficients in the second list, because none of the polynomials use "C+D*x" instead of "C" in the recurrence relation. This is assumed in the implementation!)
If the argument "x" is numerical, the function OrthoPolyNumeric is called. Otherwise, the function OrthoPolyCoeffs computes a list of coefficients, and EvaluateHornerScheme converts this list into a polynomial expression.
The algorithm used to compute the series without first computing the individual polynomials is the Clenshaw-Smith recurrence scheme. See: Yudell L. Luke. Mathematical functions and their approximations. Academic Press, N. Y., 1975.
If the argument "x" is numerical, the function OrthoPolySumNumeric is called. Otherwise, the function OrthoPolySumCoeffs computes the list of coefficients of the resulting polynomial, and EvaluateHornerScheme converts this list into a polynomial expression.
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*") |