package org.geogebra.common.cas.giac;
import java.util.Map;
import java.util.TreeMap;
import org.geogebra.common.main.App;
import org.geogebra.common.main.Feature;
/***
* # Command translation table from GeoGebra to giac # e.g. Factor[ 2(x+3) ] is
* translated to factor( 2*(x+3) ) ###
*
* Giac Constants
*
*
* DOM_INT = 2 DOM_IDENT = 6 DOM_LIST = 7 DOM_RAT = 10
*/
public class Ggb2giac {
private static Map<String, String> commandMap = new TreeMap<String, String>();
/**
* @param signature
* GeoGebra command signature (i.e. "Element.2")
* @param casSyntax
* CAS syntax, parameters as %0,%1
*/
public static void p(String signature, String casSyntax) {
// replace _ with \_ to make sure it's not replaced with "unicode95u"
commandMap.put(signature, casSyntax.replace("_", "\\_"));
}
/**
* @param app
* application, might be needed for featur
* @return map signature => syntax
*/
public static Map<String, String> getMap(App app) {
// these commands aren't supported in the CAS View
// not supported in CAS
p("CopyFreeObject.1", "?");
p("Object.1", "?");
p("CellRange.2", "?");
p("Column.1", "?");
p("Row.1", "?");
p("Cell.2", "?");
p("Append.2", "append(%0,%1)");
// simplify() to make sure Binomial[n,1] gives n
p("Binomial.2", "simplify(binomial(%0,%1))");
p("BinomialDist.3",
"[[[ggbbinarg0:=%0], [ggbbinarg1:=%1], [ggbbinarg2:=%2]],"
+ "when(type(ggbbinarg2)==DOM_LIST,sum(seq(binomial(ggbbinarg0,ggbbinarg2[j],ggbbinarg1),j,0,length(ggbbinarg2)-1)),undef)][1]");
p("BinomialDist.4",
"[[[ggbbinarg0:=%0], [ggbbinarg1:=%1], [ggbbinarg2:=%2]],"
+ "if %3==true then "
// needed for GGB-841
// if %2 is not a number for BinomialDist[n, p, k, true]
// use
// Sum[BinomialCoefficient[n, i]p^i(1-p)^(n-i), i, 0, k]
+ "when ( type(%2)==DOM_IDENT ,"
+ " expand(sum(binomial(%0,ggbtmpvari)*pow(%1,ggbtmpvari)*pow(1-%1,%0-ggbtmpvari),ggbtmpvari,0,%2)),"
+ " binomial_cdf(ggbbinarg0,ggbbinarg1,ggbbinarg2))"
+ "else binomial(ggbbinarg0,ggbbinarg2,ggbbinarg1) fi][1]");
p("Cauchy.3", "normal(1/2+1/pi*atan(((%2)-(%1))/(%0)))");
// factor over complex rationals
// [ggbans:=%0] first in case something goes wrong, eg CFactor[sqrt(21)
// - 2sqrt(7) x <complexi> + 3sqrt(3) x^2 <complexi> + 6x^3]
p("CFactor.1",
"[with_sqrt(0),[ggbcfactans:=%0],[ggbcfactans:=cfactor(ggbcfactans)],with_sqrt(1),ggbcfactans][4]");
p("CFactor.2",
"[with_sqrt(0),[ggbcfactans:=%0],[ggbcfactans:=cfactor(ggbcfactans,%1)],with_sqrt(1),ggbcfactans][4]");
// factor over complex irrationals
p("CIFactor.1",
"[with_sqrt(1),[ggbcfactans:=%0],[ggbcfactans:=cfactor(ggbcfactans)],ggbcfactans][3]");
p("CIFactor.2",
"[with_sqrt(1),[ggbcfactans:=%0],[ggbcfactans:=cfactor(ggbcfactans,%1)],ggbcfactans][3]");
p("ChiSquared.2",
// "chisquare_cdf(%0,%1)");
"igamma(%0/2,%1/2,1)");
p("Coefficients.1", "when(is_polynomial(%0)," + "coeffs(%0)," + "{})");
p("Coefficients.2", "coeffs(%0,%1)");
p("CompleteSquare.1",
" [[ggbcmpsqarg0:=expand(%0)] , when ( size(simplify(%0)) <= 3 , "
// case max 3 terms
// hack for case like x^2 + x + 0.9
// needed for GGB-126
+ " when ( size(ggbcmpsqarg0) == 2 && (size((ggbcmpsqarg0)[2]) == 2 || size((ggbcmpsqarg0)[2]) == 1) && (ggbcmpsqarg0)[2][0] != '+' , "
// case 2 terms
+ " when ( odd(degree(ggbcmpsqarg0)) == 0 , when ( degree((ggbcmpsqarg0)[2]) == 0 , "
// case px^(2n) + r
+ " [ [ [n:=degree(ggbsort(ggbcmpsqarg0)[1]) div 2] , [p:=coeffs(ggbsort(ggbcmpsqarg0)[1])[0]] , [r:=coeffs(ggbsort(ggbcmpsqarg0)[2])[0]] ] , equation(p*(lname(ggbcmpsqarg0)[0]^(2n))+r) ][1] , "
// case px^(2n) + qx^n
+ " [ [ [n:=degree(ggbsort(ggbcmpsqarg0)[1]) div 2] , [p:=coeffs(ggbsort(ggbcmpsqarg0)[1])[0]] , [q:=coeffs(ggbsort(ggbcmpsqarg0)[2])[0]] , [h:=-q/(2*p)] , [k:=(-q^2)/(4*p)] ] , when ( degree((ggbcmpsqarg0)[2]) == n , equation(p*((lname(ggbcmpsqarg0)[0])^n-h)^2+k) , ? ) ][1] ) ,"
// 2 terms with even degree
+ " ? ) , "
// case 3 term with degree 2
+ "when ( degree(ggbcmpsqarg0) == 2 , canonical_form(ggbcmpsqarg0) , "
// case 3 term with degree > 2
+ " when ( odd(degree(ggbcmpsqarg0)) == 0 && degree(ggbsort(ggbcmpsqarg0)[2]) == degree(ggbsort(ggbcmpsqarg0)[1]) div 2 && type(ggbsort(ggbcmpsqarg0)[3]) == DOM_INT , "
// case px^(2n) + qx^n + r
+ " [ [ [[n:=degree(ggbsort(ggbcmpsqarg0)[1]) div 2]] , [p:=coeffs(ggbsort(ggbcmpsqarg0)[1])[0]] , [q:=coeffs(ggbsort(ggbcmpsqarg0)[2])[0]] , [r:=coeffs(ggbsort(ggbcmpsqarg0)[3])[0]] , [h:=-q/(2*p)] , [k:=r-(q^2)/(4*p)] ] , equation(p*((lname(ggbcmpsqarg0)[0])^n-h)^2+k) ][1] , "
// invalid equation
+ "? ) ) ) , "
// term > 3
+ " ? )][1] ");
p("CommonDenominator.2", "lcm(denom(%0),denom(%1))");
// Use local function rather than subst to make sure t==5 is not
// evaluated to false before subst
p("CountIf.3",
"[[ggbcount(%1):=begin when(%0,1,0);end],sum(map(%2,loc->ggbcount(loc)))][1]");
p("CountIf.2",
"[[ggbcount(x):=begin when(%0,1,0);end],sum(map(%1,loc->ggbcount(loc)))][1]");
// p("CountIf.2", "sum(map(%1,loc->when(subst(%0,x=loc),1,0))");
p("Covariance.2", "covariance(%0,%1)");
p("Covariance.1", "normal(covariance(%0))");
// also in ExpressionNode for crossed-circle
p("Cross.2",
"[[[ggbcrossarg0:=%0], [ggbcrossarg1:=%1]],when(is_3dpoint(ggbcrossarg0)||is_3dpoint(ggbcrossarg1),point(cross(ggbcrossarg0,ggbcrossarg1)),cross(ggbcrossarg0,ggbcrossarg1))][1]");
// changed to give approximate answer (consistent with Input Bar)
// needed for eg ComplexRoot[sqrt(3)*x^2+sqrt(5)*x+sqrt(7)]
p("ComplexRoot.1", "cfsolve(%0)");
p("CSolutions.1",
"ggbsort([[[ggbcsans:=0/0],[ggbcsans:=%0],[ggbvars:=lname(ggbcsans)]],"
+ "normal(cZeros(%0,when(size(ggbvars)==1,ggbvars[0],x)))][1])");
p("CSolutions.2", "ggbsort(normal(cZeros(%0,%1)))");
// DO NOT wrap in normal() otherwise these don't work
// CSolve[z^2=k a^2,z]
// CSolve[3z^2-2a*(k+1)*z+a^2*k=0,z]
// (alternative is assume(ggbtmpvara, complex))
p("CSolve.1",
"ggbsort([[[ggbcsans:=0/0],[ggbcsans:=%0],[ggbvars:=lname(ggbcsans)]],"
+ "regroup(csolve(%0,when(size(ggbvars)==1,ggbvars[0],x)))][1])");
p("CSolve.2", "ggbsort(regroup(csolve(%0,%1)))");
p("Degree.1", "total_degree(%0,lname(%0))");
p("Degree.2", "degree(%0,%1)");
// denom() cancels down first so use getDenom()
// a/b encoded as a*(1/b)
// factor needed for eg a/b + c/d
// need to use %0 to avoid auto-simplifying eg
// Denominator[((x+1)*x)/(x+1)]
// || length(%0) > 2 is for Denominator[((x+1)*x)/(x+1)] which Giac
// stores as a product of *3* things
p("Denominator.1",
"[[ggbdenomans:=%0],when((%0)[0]=='inv', getDenom(%0), "
+ "when((%0)[0]=='*', "
+ "when((%0)[2][0]=='inv' || length(%0) > 2, getDenom(%0), getDenom(factor(ggbdenomans))),"
+ "getDenom(factor(ggbdenomans)) )" + ")][1]");
// this chooses x if it's in the expression
// otherwise the first variable alphabetcially
// when(count_eq(x,lname(%0))==0,lname(%0)[0],x)
p("Derivative.1",
"[[ggbderivarg0:=%0], regroup(regroup(diff(ggbderivarg0, " +
// check for constant
"when(length(lname(ggbderivarg0))==0,x,"
+ "when(count_eq(x,lname(ggbderivarg0))==0,lname(ggbderivarg0)[0],x)))))][1]");
p("Derivative.2", "[[[ggbderiv2arg0:=%0],[ggbderiv2arg1:=%1]],"
+ "when(type(ggbderiv2arg1)==DOM_INT,"
+ "regroup(regroup(diff(ggbderiv2arg0,when(count_eq(x,lname(ggbderiv2arg0))==0,lname(%0)[0],x),ggbderiv2arg1)))"
+ "," + "regroup(regroup(diff(ggbderiv2arg0,ggbderiv2arg1)))"
+ ")][1]");
p("Derivative.3", "regroup(regroup(diff(%0,%1,%2)))");
// det_minor for symbolic, see GGB-830
p("Determinant.1", "when(size(lname(%0))==0,det(%0),det_minor(%0))");
p("Dimension.1",
"[[ggbdimarg:=%0], when(ggbdimarg[0]=='pnt',when(is_3dpoint(ggbdimarg),3,2),dim(ggbdimarg))][1]");
p("Div.2",
"[[[ggbdivarg0:=%0],[ggbdivarg1:=%1]],if type(ggbdivarg0)==DOM_INT && type(ggbdivarg1)==DOM_INT then iquo(ggbdivarg0,ggbdivarg1) else quo(ggbdivarg0,ggbdivarg1,x) fi][1]");
p("Division.2",
"[[[ggbdivarg0:=%0],[ggbdivarg1:=%1]],if type(ggbdivarg0)==DOM_INT && type(%1)==DOM_INT then iquorem(ggbdivarg0,ggbdivarg1) else quorem(ggbdivarg0,ggbdivarg1,x) fi][1]");
p("Divisors.1", "dim(idivis(%0))");
p("DivisorsList.1", "idivis(%0)");
p("DivisorsSum.1", "sum(idivis(%0))");
// p("Dot.2", "regroup(dot(%0,%1))");
// p("Dot.2",
// "[[[ggbdotarg0:=%0], [ggbdotarg1:=%1]],
// regroup(dot(ggbdotarg0,ggbdotarg1))][1]");
p("Dot.2",
"[[[ggbdotarg0:=%0], [ggbdotarg1:=%1]],"
+ "when(type(ggbdotarg0)==DOM_LIST && subtype(ggbdotarg0)!=27,"
+
// eg lists length 4 (and not ggbvect)
"regroup(ggbdotarg0 * ggbdotarg1)" + ","
+ " regroup(xcoord(ggbdotarg0)*xcoord(ggbdotarg1)+ycoord(ggbdotarg0)*ycoord(ggbdotarg1)+zcoord(ggbdotarg0)*zcoord(ggbdotarg1))"
+ ")][1]");
// GeoGebra indexes lists from 1, giac from 0
// equations:
// (4x-3y=2x+1)[0] ='='
// (4x-3y=2x+1)[1] = left side
// (4x-3y=2x+1)[2] = right side
// expressions:
// (4x+3y-1)[0] = '+' -- no way to handle in GGB, return ?
// (4x+3y-1)[1] = 4x
// (4x+3y-1)[2] = 3y
// (4x+3y-1)[3] = -1
p("Element.2",
"[[[ggbelarg0:=%0], [ggbelarg1:=%1]],when(type(ggbelarg0)==DOM_LIST,(ggbelarg0)[ggbelarg1-1],when(ggbelarg1>0,when(ggbelarg0[0]=='pnt',?,(ggbelarg0)[ggbelarg1]),?))][1]");
// if %0[0]=='=' then %0[%1] else when(...) fi;
// GeoGebra indexes lists from 1, giac from 0
p("Element.3", "(%0)[%1 - 1,%2 - 1]");
p("Eliminate.2", "eliminate(%0,%1)");
// used in regular mode
// Giac doesn't auto-simplify
// normal so f(x):=(x^2-1)/(x-1) -> x+1 (consistent with Reduce)
// regroup so that r*r^n -> r^(n+1)
// regroup/normal swapped for improved variable order eg x^2 + a*x + b
// #5500 don't expand brackets automatically
p("Evaluate.1",
"[[[ggbevalarg:=%0],[ggbevalans:=regroup(normal(ggbevalarg))],[ggbevalans2:=regroup(ggbevalarg)]], when(length(\"\"+ggbevalans)<=length(\"\"+ggbevalans2),ggbevalans,ggbevalans2)][1]");
// split into real + imag #4522
p("Expand.1",
"[[ggbexpandarg:=%0],when(contains(ggbexpandarg,i),normal(real(ggbexpandarg)) + normal(i*im(ggbexpandarg)), normal(ggbexpandarg))][1]");
p("Exponential.2", "1-exp(-(%0)*(%1))");
p("Extremum.1",
"[[[ggbextremumfun:=%0], [ggbextans:=extrema(%0)],[ggbextvar:=when(size(lname(ggbextremumfun) intersect [x]) == 0,lname(ggbextremumfun)[0],x)]], map(ggbextans,it->point(it,normal(regroup(subst(ggbextremumfun,ggbextvar,it))))) ][1]");
p("TurningPoint.1",
"[[[ggbinflfun:=%0], [ggbinflvar:=when(size(lname(ggbinflfun) intersect [x]) == 0,lname(ggbinflfun)[0],x)],[ggbinflans:=extrema(diff(%0,ggbinflvar))]], map(ggbinflans,it->point(it,normal(regroup(subst(ggbinflfun,ggbinflvar,it))))) ][1]");
// factor over rationals
// add x so that Factor[(-k x^2 + 4k x + x^3)] gives a nicer answer
p("Factor.1",
"[with_sqrt(0),[ggbfacans:=%0],[if type(ggbfacans)==DOM_INT then ggbfacans:=ifactor(ggbfacans); else ggbfacans:=factor(ggbfacans,x); fi],with_sqrt(1),ggbfacans][4]");
p("Factor.2",
"[with_sqrt(0),[ggbfacans:=%0],[ggbfacans:=factor(ggbfacans,%1)],with_sqrt(1),ggbfacans][4]");
// factor over irrationals
p("IFactor.1",
"[with_sqrt(1),[ggbfacans:=%0],[if type(ggbfacans)==DOM_INT then ggbfacans:=ifactor(ggbfacans); else ggbfacans:=factor(ggbfacans,x); fi],ggbfacans][3]");
p("IFactor.2",
"[with_sqrt(1),[ggbfacans:=%0],[ggbfacans:=factor(ggbfacans,%1)],ggbfacans][3]");
// convert {x-1,1,x+1,1} to {{x-1,1},{x+1,1}}
p("Factors.1",
// "factors(%0)");
"[[ggbfacans:=%0],[if type(ggbfacans)==DOM_INT then calc_mode(0); ggbfacans:=ifactors(ggbfacans); calc_mode(1); else ggbfacans:=factors(ggbfacans); fi],matrix(dim(ggbfacans)/2,2,ggbfacans)][2]");
p("FDistribution.3", "fisher_cdf(%0,%1,%2)");
// alternative for exact answers
// "Beta(exact(%0)/2,%1/2,%0*%2/(%0*%2+%1),1)");
p("Flatten.1", "flatten(%0)");
p("First.1",
"[[ggbfiarg0:=%0],{when(type(ggbfiarg0)==DOM_LIST,(ggbfiarg0)[0],(ggbfiarg0)[1])}][1]");
p("First.2",
"[[[ggbfiarg0:=%0],[ggbfiarg1:=%1]],when(type(ggbfiarg0)==DOM_LIST,(ggbfiarg0)[0..ggbfiarg1-1],seq((ggbfiarg0)[j],j,1,ggbfiarg1))][1]");
// These implementations follow the one in GeoGebra
p("FitExp.1",
"[[ggbfitans:=%0],[ggbfitans:=exponential_regression(ggbfitans)],evalf(ggbfitans[1])*exp(ln(evalf(ggbfitans[0]))*x)][2]");
p("FitLog.1",
"[[ggbfitans:=%0],[ggbfitans:=logarithmic_regression(%0)],evalf(ggbfitans[0])*ln(x)+evalf(ggbfitans[1])][2]");
p("FitPoly.2",
"[[[ggbfitpans:=0/0], [ggbvar:=x], [ggbinput:=%0], [ggborder:=%1], "
+ "when(ggborder + 1 == size(ggbinput),"
// use exact fit when correct number of points
// eg FitPoly[ {(-6.64803509914449, -9.72031412828010),
// (7.22538138096244, 7.18002958385020),
// (20.0000000000000, -20.0000000000000),
// (32.4497749811568, -13.2517292323073),
// (-10.4316941391736, -13.5039731683093)} , 4]
// adapted from Polynomial.N + evalf()
+ "[[xvals := [seq(evalf(xcoord(ggbinput[j])),j=0..size(ggbinput)-1)]], [yvals := [seq(evalf(ycoord(ggbinput[j])),j=0..size(ggbinput)-1)]], [ggbfitpans := normal(lagrange(xvals,yvals,x))]]"
+ ","
// eg FitPoly[ {(0.44, 0.42), (1.7, 0.48), (2.7, 1.2),
// (3.5, 1.78), (4.36, 2.64), (5.12, 3.76), (5.78,
// 4.66)} ,3]
+ "[ggbfitpans:=normal(evalf(horner(polynomial_regression(%0,%1),x)))]"
+ ")],ggbfitpans][1]");
p("FitPow.1",
"[[ggbfitans:=%0],[ggbfitans:=power_regression(ggbfitans)],evalf(ggbfitans[1])*x^evalf(ggbfitans[0])][2]");
// Function[sin(x),0, 2 pi]
// Function[sin(p),0, 2 pi]
// Function[5,0, 1]
p("Function.3",
"[[ggbvars:=lname(%0)],[ggbvar:=when(size(ggbvars)==0,x,ggbvars[0])], when(ggbvar>=%1 && ggbvar<=%2, %0, undef)][2]");
p("Gamma.3", "igamma((%0),(%2)/(%1),1)");
p("GCD.2", "gcd(%0,%1)");
p("GCD.1", "lgcd(%0)");
// GetPrecision.1
// Groebner basis related commands.
// See http://en.wikipedia.org/wiki/Gr%C3%B6bner_basis#Monomial_ordering
// to learn more about the following.
// Also http://en.wikipedia.org/wiki/Monomial_order is very helpful.
// Naming convention follows the (first) Wikipedia article, however,
// other pieces of software
// (like Sage) may have different names. There is no common scientific
// naming for the orderings.
// 1. (Pure) lexicographical ordering (original, "classical" method):
p("GroebnerLex.1", "gbasis(%0,indets(%0),plex)");
p("GroebnerLex.2", "gbasis(%0,%1,plex)");
// We will not use the former "Groebner" command since for educational
// purposes it is crucial
// to make an emphasis on the monomial ordering.
// 2. Total degree reverse lexicographical ordering (best method), also
// called as "grevlex":
p("GroebnerDegRevLex.1", "gbasis(%0,indets(%0),revlex)");
p("GroebnerDegRevLex.2", "gbasis(%0,%1,revlex)");
// 3. Total degree lexicographical ordering (useful for elimination),
// also called as "grlex":
p("GroebnerLexDeg.1", "gbasis(%0,indets(%0),tdeg)");
p("GroebnerLexDeg.2", "gbasis(%0,%1,tdeg)");
p("HyperGeometric.5",
"[[m:=%1],[ng:=%0],[n:=%2],[kk:=%3],if %4==true then sum(binomial(m,k)*binomial((ng-m),(n-k))/binomial(ng,n),k,0,floor(kk)) "
+ "else binomial(m,kk)*binomial((ng-m),(n-kk))/binomial(ng,n) fi][4]");
p("Identity.1", "identity(round(%0))");
// #4705
p("If.2", "when(%0,%1,undef)");
p("If.3", "when(%0,%1,%2)");
// normal(regroup()) so that ImplicitDerivative[x^2 + y^2, y, x] gives a
// nice answer
// the danger is that this could multiply something out eg (x+1)^100
// (unlikely)
p("ImplicitDerivative.3", "normal(regroup(-diff(%0,%2)/diff(%0,%1)))");
p("ImplicitDerivative.1", "normal(regroup(-diff(%0,x)/diff(%0,y)))");
p("Integral.1", "regroup(integrate(%0))");
p("Integral.2", "regroup(integrate(%0,%1))");
// The symbolic value of the integral is checked against a numeric
// evaluation of the integral
// if they return different answers then a list with both values is
// returned.
// get the first element of the list to ignore the warning
// simplify() added to improve Integral[2*exp(0.5x),0,ln(4)]
// check for ? for eg Integral[ln(x)-x+4,0.45,2.07]
// check length for eg Integral[ln(x),0.45,2.07]
p("Integral.3",
"[[[ggbintans:=0/0],[ggbintans:=integrate(%0,%1,%2)], [ggbintans:=when(type(ggbintans)==DOM_LIST,ggbintans[size(ggbintans)-1],ggbintans)], [ggbintanssimplified:=simplify(ggbintans)]],"
+ "when(ggbintanssimplified==undef || length(\"\"+ggbintans)<=length(\"\"+ggbintanssimplified),regroup(ggbintans),ggbintanssimplified)][1]");
p("Integral.4",
"[[[ggbintans:=0/0],[ggbintans:=integrate(%0,%1,%2,%3)], [ggbintans:=when(type(ggbintans)==DOM_LIST,ggbintans[size(ggbintans)-1],ggbintans)], [ggbintanssimplified:=simplify(ggbintans)]],"
+ "when(ggbintanssimplified==undef || length(\"\"+ggbintans)<=length(\"\"+ggbintanssimplified),regroup(ggbintans),ggbintanssimplified)][1]");
p("IntegralBetween.4",
"[[[ggbintans:=0/0],[ggbintans:=int(%0-(%1),x,%2,%3)], [ggbintans:=when(type(ggbintans)==DOM_LIST,ggbintans[size(ggbintans)-1],ggbintans)], [ggbintanssimplified:=simplify(ggbintans)]],"
+ "when(ggbintanssimplified==undef || length(\"\"+ggbintans)<=length(\"\"+ggbintanssimplified),regroup(ggbintans),ggbintanssimplified)][1]");
p("IntegralBetween.5",
"[[[ggbintans:=0/0],[ggbintans:=int(%0-(%1),%2,%3,%4)], [ggbintans:=when(type(ggbintans)==DOM_LIST,ggbintans[size(ggbintans)-1],ggbintans)], [ggbintanssimplified:=simplify(ggbintans)]],"
+ "when(ggbintanssimplified==undef || length(\"\"+ggbintans)<=length(\"\"+ggbintanssimplified),regroup(ggbintans),ggbintanssimplified)][1]");
// p("Integral.3",
// "[[[ggbintans:=0/0],[ggbintans:=integrate(%0,%1,%2)]],"
// +
// "normal(when(type(ggbintans)==DOM_LIST,ggbintans[0],simplify(ggbintans)))][1]");
// p("Integral.4",
// "[[[ggbintans:=0/0],[ggbintans:=integrate(%0,%1,%2,%3)]],"
// +
// "normal(when(type(ggbintans)==DOM_LIST,ggbintans[0],simplify(ggbintans)))][1]");
// p("IntegralBetween.4",
// "[[[ggbintans:=0/0],[ggbintans:=int(%0-(%1),x,%2,%3)]],"
// +
// "normal(when(type(ggbintans)==DOM_LIST,ggbintans[0],simplify(ggbintans)))][1]");
// p("IntegralBetween.5",
// "[[[ggbintans:=0/0],[ggbintans:=int(%0-(%1),%2,%3,%4)]],"
// +
// "normal(when(type(ggbintans)==DOM_LIST,ggbintans[0],simplify(ggbintans)))][1]");
// need to wrap in coordinates() for
// Intersect[Curve[t,t^2,t,-10,10],Curve[t2,1-t2,t2,-10,10] ]
// but not for Intersect[x^2,x^3]
// ggbans:=0/0 to make sure if there's an error, we don't output
// previous answer
// add y= so that Intersect[(((2)*(x))+(1))/((x)-(5)),y=2] ie
// Intersect[f,a] works
p("Intersect.2",
"[[ggbinterans:=0/0]," + "[ggbinarg0:=%0]," + "[ggbinarg1:=%1],"
// Intersect[Plane, Plane]
+ "[ggbinterans:=when ( (ggbinarg0)[0] == 'pnt',"
+ "when ( (ggbinarg0)[1][0] == 'hyperplan',"
+ "when ( (ggbinarg1)[0] == 'pnt',"
// intersection is empty
+ "when (xcoord((line_inter(ggbinarg0,ggbinarg1))[1][0]) == '?', ? ,"
// create 3d line for intersection
+ "regroup(equation(cat(\"X=\","
+ "point(xcoord((line_inter(ggbinarg0,ggbinarg1))[1][0]),"
+ "ycoord((line_inter(ggbinarg0,ggbinarg1))[1][0]),"
+ "zcoord((line_inter(ggbinarg0,ggbinarg1))[1][0])),"
+ "\"+\u03BB*\","
+ "point(xcoord((line_inter(ggbinarg0,ggbinarg1))[1][1]-(line_inter(ggbinarg0,ggbinarg1))[1][0]),"
+ "ycoord((line_inter(ggbinarg0,ggbinarg1))[1][1]-(line_inter(ggbinarg0,ggbinarg1))[1][0]),"
+ "zcoord((line_inter(ggbinarg0,ggbinarg1))[1][1]-(line_inter(ggbinarg0,ggbinarg1))[1][0])))))),"
// Intersect[Plane, Cas3dLine]
+ "when ((ggbinarg1)[0] == '=' && (ggbinarg1)[1] == 'ggbtmpvarX',"
+ "inter(ggbinarg0,"
+ "line( point((ggbinarg1)[2][1][0][1],"
+ "(ggbinarg1)[2][1][1][1],"
+ "(ggbinarg1)[2][1][2][1]),"
+ "point(coeffs((ggbinarg1)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][0][1],"
+ "coeffs((ggbinarg1)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][1][1],"
+ "coeffs((ggbinarg1)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][2][1]) ))[0] ,"
// Intersect[Plane, Cmd3dLine]
+ "when (xcoord(ggbinarg1) == string(X) ,"
+ "line_inter(ggbinarg0 ,"
+ "line( point(expr(ggbinarg1)[0][2][1] , "
+ "expr(ggbinarg1)[1][2][1],"
+ "expr(ggbinarg1)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg1)[0][2],\u03BB,1) + expr(ggbinarg1)[0][2][1], "
+ "coeff(expr(ggbinarg1)[1][2],\u03BB,1) + expr(ggbinarg1)[1][2][1] , "
+ "coeff(expr(ggbinarg1)[2][2],\u03BB,1) + expr(ggbinarg1)[2][2][1]) ) ), "
// Intersect[Plane, 3dLine]
+ "when ( (xcoord(ggbinarg1))[0] == '=' && string((xcoord(ggbinarg1))[1]) == string(X) ,"
+ "line_inter(ggbinarg0,"
+ "line( point( (ggbinarg1)[0][2] , (ggbinarg1)[1][2] , (ggbinarg1)[2][2][1] ) ,"
+ "point( (ggbinarg1[2][2][2])[2][0] + (ggbinarg1)[0][2], "
+ "(ggbinarg1[2][2][2])[2][1] + (ggbinarg1)[1][2] ,"
+ "(ggbinarg1[2][2][2])[2][2] + (ggbinarg1)[2][2][1] ) ) ), "
// Intersect[Plane, 2dLine]
// Intersect[Plane, Cmd2dLine]
+ "when ( type(xcoord(ggbinarg1)) == DOM_INT && type(grad(ggbinarg1,x)[1]) == DOM_INT ,"
+ "line_inter(ggbinarg0,"
+ "line(point(re(subst(parameq(line(ggbinarg1),u),u=1)),"
+ "im(subst(parameq(line(ggbinarg1),u),u=1)),0),"
+ "point(re(subst(parameq(line(ggbinarg1),u),u=2)),"
+ "im(subst(parameq(line(ggbinarg1),u),u=2)),0)) ) ,"
+ "? ) ) ) ) ) ,"
// Intersect[Point, 2dLine]
+ "when ( same((subst(ggbinarg1,x=xcoord(ggbinarg0),y=ycoord(ggbinarg0)))[1],"
+ "(subst(ggbinarg1,x=xcoord(ggbinarg0),y=ycoord(ggbinarg0)))[2]) == true ,"
+ "ggbinarg0, ?) ),"
// Intersect[Cmd3dLine, Plane]
+ "when (inString(string(ggbinarg0),\"X\") <> -1,"
+ "when ( xcoord(ggbinarg0) == string(X) ,"
+ "when ( (ggbinarg1)[0] == 'pnt' ,"
+ "line_inter(line( point(expr(ggbinarg0)[0][2][1] , "
+ "expr(ggbinarg0)[1][2][1],"
+ "expr(ggbinarg0)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg0)[0][2],\u03BB,1) + expr(ggbinarg0)[0][2][1], "
+ "coeff(expr(ggbinarg0)[1][2],\u03BB,1) + expr(ggbinarg0)[1][2][1] , "
+ "coeff(expr(ggbinarg0)[2][2],\u03BB,1) + expr(ggbinarg0)[2][2][1]) ),"
+ "ggbinarg1),"
// Intersect[Cmd3dLine, Cas3dLine]
+ "when ((ggbinarg1)[0] == '=' && (ggbinarg1)[1] == 'ggbtmpvarX',"
+ "inter(line( point(expr(ggbinarg0)[0][2][1] , "
+ "expr(ggbinarg0)[1][2][1],"
+ "expr(ggbinarg0)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg0)[0][2],\u03BB,1) + expr(ggbinarg0)[0][2][1], "
+ "coeff(expr(ggbinarg0)[1][2],\u03BB,1) + expr(ggbinarg0)[1][2][1] , "
+ "coeff(expr(ggbinarg0)[2][2],\u03BB,1) + expr(ggbinarg0)[2][2][1]) ),"
+ "line( point((ggbinarg1)[2][1][0][1],"
+ "(ggbinarg1)[2][1][1][1],"
+ "(ggbinarg1)[2][1][2][1]),"
+ "point(coeffs((ggbinarg1)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][0][1],"
+ "coeffs((ggbinarg1)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][1][1],"
+ "coeffs((ggbinarg1)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][2][1]) ))[0] ,"
// Intersect[Cmd3dLine, Cmd3dLine]
+ "when (xcoord(ggbinarg1) == string(X) ,"
+ "line_inter(line( point(expr(ggbinarg0)[0][2][1] , "
+ "expr(ggbinarg0)[1][2][1],"
+ "expr(ggbinarg0)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg0)[0][2],\u03BB,1) + expr(ggbinarg0)[0][2][1], "
+ "coeff(expr(ggbinarg0)[1][2],\u03BB,1) + expr(ggbinarg0)[1][2][1] , "
+ "coeff(expr(ggbinarg0)[2][2],\u03BB,1) + expr(ggbinarg0)[2][2][1]) ), "
+ "line( point(expr(ggbinarg1)[0][2][1] , "
+ "expr(ggbinarg1)[1][2][1],"
+ "expr(ggbinarg1)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg1)[0][2],\u03BB,1) + expr(ggbinarg1)[0][2][1], "
+ "coeff(expr(ggbinarg1)[1][2],\u03BB,1) + expr(ggbinarg1)[1][2][1] , "
+ "coeff(expr(ggbinarg1)[2][2],\u03BB,1) + expr(ggbinarg1)[2][2][1]) )) ,"
// Intersect[Cmd3dLine, 3dLine]
+ "when ( (xcoord(ggbinarg1))[0] == '=' && string((xcoord(ggbinarg1))[1]) == string(X) , "
+ "line_inter(line( point(expr(ggbinarg0)[0][2][1] , "
+ "expr(ggbinarg0)[1][2][1],"
+ "expr(ggbinarg0)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg0)[0][2],\u03BB,1) + expr(ggbinarg0)[0][2][1], "
+ "coeff(expr(ggbinarg0)[1][2],\u03BB,1) + expr(ggbinarg0)[1][2][1] , "
+ "coeff(expr(ggbinarg0)[2][2],\u03BB,1) + expr(ggbinarg0)[2][2][1]) ) ,"
+ "line( point( (ggbinarg1)[0][2] , (ggbinarg1)[1][2] , (ggbinarg1)[2][2][1] ) ,"
+ "point( (ggbinarg1[2][2][2])[2][0] + (ggbinarg1)[0][2], "
+ "(ggbinarg1[2][2][2])[2][1] + (ggbinarg1)[1][2] ,"
+ "(ggbinarg1[2][2][2])[2][2] + (ggbinarg1)[2][2][1] ) ) ),"
// Intersect[Cmd3dLine, 2dLine]
// Intersect[Cmd3dLine,Cmd2dLine]
+ "when (type(xcoord(ggbinarg1)) == DOM_INT && type(grad(ggbinarg1,x)[1]) == DOM_INT,"
+ "line_inter(line( point(expr(ggbinarg0)[0][2][1] , "
+ "expr(ggbinarg0)[1][2][1],"
+ "expr(ggbinarg0)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg0)[0][2],\u03BB,1) + expr(ggbinarg0)[0][2][1], "
+ "coeff(expr(ggbinarg0)[1][2],\u03BB,1) + expr(ggbinarg0)[1][2][1] , "
+ "coeff(expr(ggbinarg0)[2][2],\u03BB,1) + expr(ggbinarg0)[2][2][1]) ) ,"
+ "line(point(re(subst(parameq(line(ggbinarg1),u),u=1)),"
+ "im(subst(parameq(line(ggbinarg1),u),u=1)),0),"
+ "point(re(subst(parameq(line(ggbinarg1),u),u=2)),"
+ "im(subst(parameq(line(ggbinarg1),u),u=2)),0)) ),"
+ " ? ) ) ) ) ),"
// Intersect[3dLine, Plane]
+ "when ( (xcoord(ggbinarg0))[0] == '=' && string((xcoord(ggbinarg0))[1]) == string(X),"
+ "when ( (ggbinarg1)[0] == 'pnt',"
+ "line_inter( line( point( (ggbinarg0)[0][2] , (ggbinarg0)[1][2] , (ggbinarg0)[2][2][1] ) ,"
+ "point( (ggbinarg0[2][2][2])[2][0] + (ggbinarg0)[0][2], "
+ "(ggbinarg0[2][2][2])[2][1] + (ggbinarg0)[1][2] ,"
+ " (ggbinarg0[2][2][2])[2][2] + (ggbinarg0)[2][2][1] ) ) ,"
+ "ggbinarg1) ,"
// Intersect[3dLine, Cas3dLine]
+ "when ((ggbinarg1)[0] == '=' && (ggbinarg1)[1] == 'ggbtmpvarX',"
+ "inter(line( point( (ggbinarg0)[0][2] , (ggbinarg0)[1][2] , (ggbinarg0)[2][2][1] ) ,"
+ "point( (ggbinarg0[2][2][2])[2][0] + (ggbinarg0)[0][2], "
+ "(ggbinarg0[2][2][2])[2][1] + (ggbinarg0)[1][2] ,"
+ " (ggbinarg0[2][2][2])[2][2] + (ggbinarg0)[2][2][1] ) ) ,"
+ "line( point((ggbinarg1)[2][1][0][1],"
+ "(ggbinarg1)[2][1][1][1],"
+ "(ggbinarg1)[2][1][2][1]),"
+ "point(coeffs((ggbinarg1)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][0][1],"
+ "coeffs((ggbinarg1)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][1][1],"
+ "coeffs((ggbinarg1)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][2][1]) ))[0] , "
// Intersect[3dLine, Cmd3dLine]
+ "when (xcoord(ggbinarg1) == string(X),"
+ "line_inter( line( point( (ggbinarg0)[0][2] , (ggbinarg0)[1][2] , (ggbinarg0)[2][2][1] ) ,"
+ "point( (ggbinarg0[2][2][2])[2][0] + (ggbinarg0)[0][2], "
+ "(ggbinarg0[2][2][2])[2][1] + (ggbinarg0)[1][2] ,"
+ " (ggbinarg0[2][2][2])[2][2] + (ggbinarg0)[2][2][1] ) ) ,"
+ "line( point(expr(ggbinarg1)[0][2][1] , "
+ "expr(ggbinarg1)[1][2][1],"
+ "expr(ggbinarg1)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg1)[0][2],\u03BB,1) + expr(ggbinarg1)[0][2][1], "
+ "coeff(expr(ggbinarg1)[1][2],\u03BB,1) + expr(ggbinarg1)[1][2][1] , "
+ "coeff(expr(ggbinarg1)[2][2],\u03BB,1) + expr(ggbinarg1)[2][2][1]) )),"
// Intersect[3dLine, 2dLine]
+ "when ( (type(xcoord(ggbinarg1)) == DOM_INT && type(grad(ggbinarg1,x)[1]) == DOM_INT) "
// Intersect[3dLine, Cmd2dLine]
+ "|| ((ggbinarg1)[0] == '=' && (ggbinarg1)[1] == 'y'),"
+ "line_inter( line( point( (ggbinarg0)[0][2] , (ggbinarg0)[1][2] , (ggbinarg0)[2][2][1] ) ,"
+ "point( (ggbinarg0[2][2][2])[2][0] + (ggbinarg0)[0][2], "
+ "(ggbinarg0[2][2][2])[2][1] + (ggbinarg0)[1][2] ,"
+ "(ggbinarg0[2][2][2])[2][2] + (ggbinarg0)[2][2][1] ) ) ,"
+ "line(point(re(subst(parameq(line(ggbinarg1),u),u=1)),"
+ "im(subst(parameq(line(ggbinarg1),u),u=1)),0),"
+ "point(re(subst(parameq(line(ggbinarg1),u),u=2)),"
+ "im(subst(parameq(line(ggbinarg1),u),u=2)),0)) ) , "
// Intersect[3dLine, 3dLine]
+ "when ( (xcoord(ggbinarg1))[0] == '=' && string((xcoord(ggbinarg1))[1]) == string(X) ,"
+ " line_inter( line( point( (ggbinarg0)[0][2] , (ggbinarg0)[1][2] , (ggbinarg0)[2][2][1] ) ,"
+ "point( (ggbinarg0[2][2][2])[2][0] + (ggbinarg0)[0][2], "
+ "(ggbinarg0[2][2][2])[2][1] + (ggbinarg0)[1][2] ,"
+ " (ggbinarg0[2][2][2])[2][2] + (ggbinarg0)[2][2][1] ) ) ,"
+ "line( point( (ggbinarg1)[0][2] , (ggbinarg1)[1][2] , (ggbinarg1)[2][2][1] ) ,"
+ "point( (ggbinarg1[2][2][2])[2][0] + (ggbinarg1)[0][2], "
+ "(ggbinarg1[2][2][2])[2][1] + (ggbinarg1)[1][2] ,"
+ " (ggbinarg1[2][2][2])[2][2] + (ggbinarg1)[2][2][1] ) ) ) , ? ) ) ) ) ) ,"
// Intersect[Cas3dLine, Cas3dLine]
+ "when ( (ggbinarg0)[0] == '=' && (ggbinarg0)[1] == 'ggbtmpvarX',"
+ "when ( (ggbinarg1)[0] == '=' && (ggbinarg1)[1] == 'ggbtmpvarX',"
+ "inter( line( point((ggbinarg0)[2][1][0][1],"
+ "(ggbinarg0)[2][1][1][1],"
+ "(ggbinarg0)[2][1][2][1]),"
+ "point(coeffs((ggbinarg0)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][0][1],"
+ "coeffs((ggbinarg0)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][1][1],"
+ "coeffs((ggbinarg0)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][2][1]) ),"
+ "line( point((ggbinarg1)[2][1][0][1],"
+ "(ggbinarg1)[2][1][1][1],"
+ "(ggbinarg1)[2][1][2][1]),"
+ "point(coeffs((ggbinarg1)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][0][1],"
+ "coeffs((ggbinarg1)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][1][1],"
+ "coeffs((ggbinarg1)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg1)[2][1][2][1]) ))[0] ,"
// Intersect[Cas3dLine, Plane]
+ "when ((ggbinarg1)[0] == 'pnt' && (ggbinarg1)[1][0] == 'hyperplan',"
+ "inter( line( point((ggbinarg0)[2][1][0][1],"
+ "(ggbinarg0)[2][1][1][1],"
+ "(ggbinarg0)[2][1][2][1]),"
+ "point(coeffs((ggbinarg0)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][0][1],"
+ "coeffs((ggbinarg0)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][1][1],"
+ "coeffs((ggbinarg0)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][2][1]) ),ggbinarg1)[0],"
// Intersect[Cas3dLine, Cmd3dLine]
+ "when (xcoord(ggbinarg1) == string(X),"
+ "inter( line( point((ggbinarg0)[2][1][0][1],"
+ "(ggbinarg0)[2][1][1][1],"
+ "(ggbinarg0)[2][1][2][1]),"
+ "point(coeffs((ggbinarg0)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][0][1],"
+ "coeffs((ggbinarg0)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][1][1],"
+ "coeffs((ggbinarg0)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][2][1]) ),"
+ "line( point(expr(ggbinarg1)[0][2][1] , "
+ "expr(ggbinarg1)[1][2][1],"
+ "expr(ggbinarg1)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg1)[0][2],\u03BB,1) + expr(ggbinarg1)[0][2][1], "
+ "coeff(expr(ggbinarg1)[1][2],\u03BB,1) + expr(ggbinarg1)[1][2][1] , "
+ "coeff(expr(ggbinarg1)[2][2],\u03BB,1) + expr(ggbinarg1)[2][2][1]) ) )[0] ,"
// Intersect[Cas3dLine, 3dLine]
+ "inter( line( point((ggbinarg0)[2][1][0][1],"
+ "(ggbinarg0)[2][1][1][1],"
+ "(ggbinarg0)[2][1][2][1]),"
+ "point(coeffs((ggbinarg0)[2][1][0], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][0][1],"
+ "coeffs((ggbinarg0)[2][1][1], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][1][1],"
+ "coeffs((ggbinarg0)[2][1][2], ggbtmpvar\u03BB,1) + (ggbinarg0)[2][1][2][1]) ),"
+ "line( point( (ggbinarg1)[0][2] , (ggbinarg1)[1][2] , (ggbinarg1)[2][2][1] ) ,"
+ "point( (ggbinarg1[2][2][2])[2][0] + (ggbinarg1)[0][2], "
+ "(ggbinarg1[2][2][2])[2][1] + (ggbinarg1)[1][2] ,"
+ " (ggbinarg1[2][2][2])[2][2] + (ggbinarg1)[2][2][1] ) ) )[0] ) ) ) , ?) ) ) ,"
// Intersect[2dLine, Plane]
// Intersect[Cmd2dLine, Plane]
+ "when ( type(xcoord(ggbinarg0)) == DOM_INT && type(grad(ggbinarg0,x)[1]) == DOM_INT ,"
+ "when ( (ggbinarg1)[0] == 'pnt' ,"
+ "when ( (ggbinarg1)[1][0] == 'hyperplan', "
+ "line_inter(line(point(re(subst(parameq(line(ggbinarg0),u),u=1)),"
+ "im(subst(parameq(line(ggbinarg0),u),u=1)),0),"
+ "point(re(subst(parameq(line(ggbinarg0),u),u=2)),"
+ "im(subst(parameq(line(ggbinarg0),u),u=2)),0)),"
+ "ggbinarg1) ,"
// Intersect[2dLine, Point]
+ "when ( same(subst(ggbinarg0,x=xcoord(ggbinarg1),y=ycoord(ggbinarg1))[1],"
+ "subst(ggbinarg0,x=xcoord(ggbinarg1),y=ycoord(ggbinarg1))[2]) == true,"
+ "ggbinarg1, ? ) ) , "
// Intersect[2dLine, Cmd3dLine]
// Intersect[Cmd2dLine, Cmd3dLine]
+ "when(xcoord(ggbinarg1) == string(X),"
+ "line_inter(line(point(re(subst(parameq(line(ggbinarg0),u),u=1)),"
+ "im(subst(parameq(line(ggbinarg0),u),u=1)),0),"
+ "point(re(subst(parameq(line(ggbinarg0),u),u=2)),"
+ "im(subst(parameq(line(ggbinarg0),u),u=2)),0)),"
+ "line( point(expr(ggbinarg1)[0][2][1] , "
+ "expr(ggbinarg1)[1][2][1],"
+ "expr(ggbinarg1)[2][2][1] ),"
+ "point(coeff(expr(ggbinarg1)[0][2],\u03BB,1) + expr(ggbinarg1)[0][2][1], "
+ "coeff(expr(ggbinarg1)[1][2],\u03BB,1) + expr(ggbinarg1)[1][2][1] , "
+ "coeff(expr(ggbinarg1)[2][2],\u03BB,1) + expr(ggbinarg1)[2][2][1]) ) ) , "
// Intersect[2dLine, 2dLine]
+ "when ( (type(xcoord(ggbinarg1)) == DOM_INT && type(grad(ggbinarg1,x)[1]) == DOM_INT)"
// Intersect[2dLine, Cmd2dLine]
// Intersect[Cmd2dLine,Cmd2dLine]
+ "|| ((ggbinarg1)[0] == '=' && (ggbinarg1)[1] == 'y') ,"
+ "inter(ggbinarg0,ggbinarg1) ,"
// Intersect[2dLine,3dLine]
// Intersect[Cmd2dLine, 3dLine]
+ "when ( (xcoord(ggbinarg1))[0] == '=' && string((xcoord(ggbinarg1))[1]) == string(X) ,"
+ "line_inter(line(point(re(subst(parameq(line(ggbinarg0),u),u=1)),"
+ "im(subst(parameq(line(ggbinarg0),u),u=1)),0),"
+ "point(re(subst(parameq(line(ggbinarg0),u),u=2)),"
+ "im(subst(parameq(line(ggbinarg0),u),u=2)),0)),"
+ "line( point( (ggbinarg1)[0][2] , (ggbinarg1)[1][2] , (ggbinarg1)[2][2][1] ) ,"
+ "point( (ggbinarg1[2][2][2])[2][0] + (ggbinarg1)[0][2], "
+ "(ggbinarg1[2][2][2])[2][1] + (ggbinarg1)[1][2] ,"
+ " (ggbinarg1[2][2][2])[2][2] + (ggbinarg1)[2][2][1] ) ) ) , ? ) ) ) ),"
// Intersect[Cmd2dLine, 2dLine]
+ "normal(inter(when(ggbinarg0[0]=='=',ggbinarg0,y=ggbinarg0),"
+ "when(ggbinarg1[0]=='=',ggbinarg1,y=ggbinarg1))) "
+ " ) ) ) ]," + "ggbinterans][4]");
// Giac currently uses approximation for this
// p("Conic.5", "equation(conic((%0),(%1),(%2),(%3),(%4)))");
// http://www.had2know.com/academics/conic-section-through-five-points.html
// exact method
p("Conic.5",
"[[[M:=0/0],[A:=(0/0,0/0)],[B:=(0/0,0/0)],[C:=(0/0,0/0)],[D:=(0/0,0/0)],[E:=(0/0,0/0)]],"
+
// "[[A:=%0],[B:=%1],[C:=%2],[D:=%3],[E:=%4]],"+
"[[A:=(real(%0[1]),im(%0[1]))],[B:=(real(%1[1]),im(%1[1]))],[C:=(real(%2[1]),im(%2[1]))],[D:=(real(%3[1]),im(%3[1]))],[E:=(real(%4[1]),im(%4[1]))],],"
+ "[M:={{x^2,x*y,y^2,x,y,1},{A[0]^2,A[0]*A[1],A[1]^2,A[0],A[1],1},{B[0]^2,B[0]*B[1],B[1]^2,B[0],B[1],1},{C[0]^2,C[0]*C[1],C[1]^2,C[0],C[1],1},{D[0]^2,D[0]*D[1],D[1]^2,D[0],D[1],1},{E[0]^2,E[0]*E[1],E[1]^2,E[0],E[1],1}}],"
+ "[M:=det(M)]," +
// eg Conic[(5,0),(-5,0),(0,5),(0,-5),(4,1)]
// simplify to x^2 +2 x y + y^2 - 25 from 10000x^2 +
// 20000x
// y + 10000y^2 - 250000
"[hcf:=factors(M)[0]],"
+ "when(type(hcf)==DOM_INT,normal(M/hcf)=0,M=0)"
+ "][5]");
// version using Giac's internal commands: slower and not robust
// (converts to parametric form as an intermediate step)
// Ellipse[point, point, point/number]
// p("Ellipse.3", "equation(ellipse(%0,%1,%2))");
// Hyperbola[point, point, point/number]
// p("Hyperbola.3", "equation(hyperbola(%0,%1,%2))");
// adapted from GeoConicND.setEllipseHyperbola()
final String ellipseHyperbola1 = "[[" + "[ggbellipsearg0:=%0],"
+ "[ggbellipsearg1:=%1]," + "[a:=0/0]," + "[b1:=0/0],"
+ "[b2:=0/0]," + "[c1:=0/0]," + "[c2:=0/0]," + "[a:=%2],"
+ "[b1:=xcoord(ggbellipsearg0)],"
+ "[b2:=ycoord(ggbellipsearg0)],"
+ "[c1:=xcoord(ggbellipsearg1)],"
+ "[c2:=ycoord(ggbellipsearg1)]," +
// AlgoEllipseFociPoint, AlgoHyperbolaFociPoint
"[a := when(%2[0]=='pnt',(sqrt((b1-real(a[1]))^2+(b2-im(a[1]))^2) ";
final String ellipseHyperbola2 = "sqrt((c1-real(a[1]))^2+(c2-im(a[1]))^2))/2,a)],"
+ "[diff1 := b1 - c1]," + "[diff2 := b2 - c2],"
+ "[sqsumb := b1 * b1 + b2 * b2],"
+ "[sqsumc := c1 * c1 + c2 * c2],"
+ "[sqsumdiff := sqsumb - sqsumc]," + "[a2 := 2 * a],"
+ "[asq4 := a2 * a2]," + "[asq := a * a],"
+ "[afo := asq * asq],"
+ "[ggbeherans:=normal(simplify(4 * (a2 - diff1) * (a2 + diff1) * x^2 -8 * diff1 * diff2 * x * y + 4 * (a2 - diff2) * (a2 + diff2)* y^2 -4 * (asq4 * (b1 + c1) - diff1 * sqsumdiff)*x - 4 * (asq4 * (b2 + c2) - diff2 * sqsumdiff)*y-16 * afo - sqsumdiff * sqsumdiff + 8 * asq * (sqsumb + sqsumc)))]],"
+
// simplify (...)/1000 = 0
"when(type(denom(ggbeherans))==DOM_INT,numer(ggbeherans)=0,ggbeherans=0)][1]";
// simplify (...)/1000 = 0
// "[ggbans:=numer(ggbans)],"+
// simplify eg 28x^2 - 24x y - 160x + 60y^2 - 96y + 256 = 0
// "[hcf:=factors(ggbans)[0]]],"+
// "when(type(hcf)==DOM_INT,normal(ggbans/hcf)=0,ggbans=0)][1]";
p("Ellipse.3", ellipseHyperbola1 + "+" + ellipseHyperbola2);
p("Hyperbola.3", ellipseHyperbola1 + "-" + ellipseHyperbola2);
p("Intersection.2", "%0 intersect %1");
p("Iteration.3", "regroup((unapply(%0,x)@@%2)(%1))");
p("IterationList.3",
"[[ggbilans(f,x0,n):=begin local l,k; l:=[x0]; for k from 1 to n do l[k]:=regroup(f(l[k-1])); od; l; end],ggbilans(unapply(%0,x),%1,%2)][1]");
p("PointList.1",
// solution is 3D
"when ( size((%0)[0]) == 3,"
// result of Solve, eg {{x=7,y=7,z=7}}
+ " flatten1(coordinates(map(%0,t->when ((flatten1(t))[0][0] == '=' && type((flatten1(t))[0][2]) == 'DOM_INT' , "
+ "point((flatten1(t))[0][2],(flatten1(t))[1][2],(flatten1(t))[2][2]) ,"
+ "when (type(flatten1(t)[0]) == DOM_INT , "
// result of Solution, eg (7 7 7)
+ "point(t[0],t[1],t[2]),"
// result of Solve as 3D Line
+ "point((flatten1(t))[0][2],(flatten1(t))[1][2],(flatten1(t))[2][2]) ) ) ) ) ), "
+ "when ( type((%0)[0]) == DOM_COMPLEX || (type((%0)[0]) == DOM_SYMBOLIC && (%0)[0][0] == '*'"
+ "&& (%0)[0][1] == i), %0, "
+ "flatten1(coordinates(map(%0,t->when(t[0]=='=',point(re(t[2]),im(t[2])),t)) ) ) ) )");
p("RootList.1", "apply(x->convert([x,0],25),%0)");
p("Invert.1",
"[[ggbinvans:=0/0], [ggbinvarg:=%0], [ggbinvans:=when(type(ggbinvarg)!=DOM_LIST,"
+
// invert function (answer is function, not mapping)
"subst(right(revlist([op(solve(tmpvar=ggbinvarg,lname(ggbinvarg)[0]))])[0]),tmpvar,lname(ggbinvarg)[0])"
+ "," +
// invert matrix
"when(when(length(ggbinvarg)>0,length(ggbinvarg) ==length(ggbinvarg[0]),false),inv(ggbinvarg),?))"
+ "],ggbinvans][3]");
p("IsPrime.1", "isprime(%0)");
// flatten1 is non-recursive flatten
p("Join.N", "flatten1(%)");
p("Laplace.1",
"[[ggblaparg0:=%0],when(lname(ggblaparg0)[0]=ggbtmpvart, laplace(ggblaparg0, ggbtmpvart, ggbtmpvars), laplace(ggblaparg0, lname(ggblaparg0)[0]))][1]");
p("Laplace.2", "laplace(%0, %1)");
p("Laplace.3", "laplace(%0, %1, %2)");
p("InverseBinomial.3", "binomial_icdf(%0,%1,max(0,%2-0.000000000001))");
p("InverseLaplace.1",
"[[ggblaparg0:=%0],when(lname(ggblaparg0)[0]=ggbtmpvars, ilaplace(ggblaparg0, ggbtmpvars, ggbtmpvart), ilaplace(ggblaparg0, lname(ggblaparg0)[0]))][1]");
p("InverseLaplace.2", "ilaplace(%0, %1)");
p("InverseLaplace.3", "ilaplace(%0, %1, %2)");
p("Last.1",
"[[ggblastarg0:=%0],{when(type(ggblastarg0)==DOM_LIST,(ggblastarg0)[size(ggblastarg0)-1],(ggblastarg0)[dim(ggblastarg0)])}][1]");
p("Last.2",
"[[[ggblastarg0:=%0],[ggblastarg1:=%1]],when(type(ggblastarg0)==DOM_LIST,(ggblastarg0)[size(ggblastarg0)-ggblastarg1..size(ggblastarg0)-1],seq((ggblastarg0)[j],j,dim(ggblastarg0)-ggblastarg1+1,dim(ggblastarg0)))][1]");
p("LCM.1", "lcm(%0)");
p("LCM.2", "lcm(%0,%1)");
p("LeftSide.1",
"[[ggbleftarg0:=%0],when(type(ggbleftarg0)==DOM_LIST,map(ggbleftarg0,"
+ "t->when(t[0] == '=',left(t),?)),"
// LeftSide only defined for equations
// see GGB-1116
+ "when ((ggbleftarg0)[0] == '=',"
+ "left(ggbleftarg0)," + "?))][1]");
p("LeftSide.2", "[[ggbleftarg0:=%0],"
+ "when(ggbleftarg0[%1-1][0] == '=',left(ggbleftarg0[%1-1]),?)][1]");
// subtype 27 is ggbvect()
p("Length.1",
"[[ggbv:=%0],regroup(when(ggbv[0]=='pnt' || (type(ggbv)==DOM_LIST && subtype(ggbv)==27), l2norm(ggbv),size(ggbv)))][1]");
p("Length.3", "arcLen(%0,%1,%2)");
p("Length.4", "arcLen(%0,%1,%2,%3)");
// regroup so that exp(1)^2 is simplified
// regroup(inf) doesn't work, so extra check needed
p("Limit.2",
"[[ggblimvans:=?],[ggblimvans:=limit(%0,%1)], [ggblimvans:=when(ggblimvans==inf || ggblimvans==-inf || ggblimvans==undef,ggblimvans,regroup(ggblimvans))],ggblimvans][3]");
p("Limit.3",
"[[ggblimvans:=?],[ggblimvans:=limit(%0,%1,%2)], [ggblimvans:=when(ggblimvans==inf || ggblimvans==-inf || ggblimvans==undef,ggblimvans,regroup(ggblimvans))],ggblimvans][3]");
p("LimitAbove.2",
"[[ggblimvans:=?],[ggblimvans:=limit(%0,x,%1,1)], [ggblimvans:=when(ggblimvans==inf || ggblimvans==-inf || ggblimvans==undef,ggblimvans,regroup(ggblimvans))],ggblimvans][3]");
p("LimitAbove.3",
"[[ggblimvans:=?],[ggblimvans:=limit(%0,%1,%2,1)], [ggblimvans:=when(ggblimvans==inf || ggblimvans==-inf || ggblimvans==undef,ggblimvans,regroup(ggblimvans))],ggblimvans][3]");
p("LimitBelow.2",
"[[ggblimvans:=?],[ggblimvans:=limit(%0,x,%1,-1)], [ggblimvans:=when(ggblimvans==inf || ggblimvans==-inf || ggblimvans==undef,ggblimvans,regroup(ggblimvans))],ggblimvans][3]");
p("LimitBelow.3",
"[[ggblimvans:=?],[ggblimvans:=limit(%0,%1,%2,-1)], [ggblimvans:=when(ggblimvans==inf || ggblimvans==-inf || ggblimvans==undef,ggblimvans,regroup(ggblimvans))],ggblimvans][3]");
p("Max.N",
"[[ggbmaxarg:=%],when(type(ggbmaxarg)==DOM_LIST, when(type((ggbmaxarg)[0])==DOM_LIST, ?, max(ggbmaxarg)), ?)][1]");
p("MatrixRank.1", "rank(%0)");
p("Mean.1", "mean(%0)");
p("Median.1", "median(%0)");
p("Min.N",
"[[ggbminarg:=%],when(type(ggbminarg)==DOM_LIST, when(type((ggbminarg)[0])==DOM_LIST, ?, min(ggbminarg)), ?)][1]");
p("MixedNumber.1", "propfrac(%0)");
p("Mod.2",
"[[[ggbmodarg0:=%0],[ggbmodarg1:=%1]],if type(ggbmodarg0)==DOM_INT && type(ggbmodarg1)==DOM_INT then irem(ggbmodarg0,ggbmodarg1) else rem(ggbmodarg0,ggbmodarg1,x) fi][1]");
p("NextPrime.1", "nextprime(%0)");
p("NIntegral.3", "romberg(%%0,%%1,%%2)");
p("NIntegral.4", "romberg(%%0,%%1,%%2,%%3)");
p("Normal.3", "normald_cdf(%0,%1,%2)");
p("Normal.4",
"[[[ggbnormarg0:=%0],[ggbnormarg1:=%1],[ggbnormarg2:=%2]],if %3==true then normald_cdf(ggbnormarg0,ggbnormarg1,ggbnormarg2) else (1/sqrt(2*pi*((ggbnormarg1)^2))) * exp(-((ggbnormarg2-(ggbnormarg0))^2) / (2*((ggbnormarg1)^2))) fi][1]");
p("nPr.2", "perm(%0,%1)");
// #4124 / TRAC-3835 wrap input in evalf
// #4124 / evalf removed, changed to %%0 to use new "numeric"
// StringTemplate
p("NSolve.1",
"ggbsort([[ggbnsans:=(%%0)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,"
+
// eg NSolve[{pi / x = cos(x - 2y), 2 y - pi = sin(x)}]
"[[ggbvars:=lname(ggbnsans)],[ggbnsans:=fsolve(ggbnsans,ggbvars)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,when(type(ggbnsans[0])==DOM_LIST,ggbnsans[0],ggbnsans),[ggbnsans])],seq(ggbvars[irem(j,dim(ggbnsans))]=ggbnsans[j],j,0,dim(ggbnsans)-1)][3],"
+
// eg NSolve[a^4 + 34a^3 = 34]
// regroup() added for
// NSolve[BC^2=4^2+3^2-2*4*3*cos(50degrees)]
"[[ggbvars:=lname(ggbnsans)],[ggbnsans:=fsolve(regroup(ggbnsans),ggbvars[0])],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,ggbnsans,[ggbnsans])],"
+ "when ( dim(ggbnsans) == 0 , {} , seq(ggbvars[0]=ggbnsans[j],j,0,dim(ggbnsans)-1) )][3])],"
+ "ggbnsans][2])");
p("NSolve.2",
"ggbsort([[ggbnsans:=(%%0)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,"
+
// eg NSolve[{pi / x = cos(x - 2y), 2 y - pi =
// sin(x)},{x=1,y=1}]
// eg NSolve[{pi / x = cos(x - 2y), 2 y - pi =
// sin(x)},{x,y}]
// eg NSolve[{3=c*a^5, 3=c*a^4},{a,c}]
"[[ggbvars:=seq(left(%%1[j]),j,0,dim(%%1)-1)],[ggbnsans:=fsolve(ggbnsans,%%1)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,when(type(ggbnsans[0])==DOM_LIST,ggbnsans[0],ggbnsans),[ggbnsans])],seq(ggbvars[irem(j,dim(ggbnsans))]=ggbnsans[j],j,0,dim(ggbnsans)-1)][3],"
+
// eg NSolve[a^4 + 34a^3 = 34, a=3]
// eg NSolve[a^4 + 34a^3 = 34, a]
"[[ggbvars:=when(type(%%1)==DOM_LIST,left(%%1[0]),left(%%1))],[ggbnsans:=fsolve(ggbnsans,%%1)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,ggbnsans,[ggbnsans])],seq(ggbvars=ggbnsans[j],j,0,dim(ggbnsans)-1)][3])],"
+ "ggbnsans][2])");
// fsolve starts at x=0 if no initial value is specified and if the
// search is not successful
// it will try a few random starting points.
p("NSolutions.1",
"ggbsort([[ggbnsans:=(%%0)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,"
+
// eg NSolutions[{pi / x = cos(x - 2y), 2 y - pi =
// sin(x)}]
"[[ggbvars:=lname(ggbnsans)],[ggbnsans:=fsolve(ggbnsans,ggbvars)],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,ggbnsans,[ggbnsans])],ggbnsans][3],"
+
// eg NSolutions[a^4 + 34a^3 = 34]
"[[ggbvars:=lname(ggbnsans)],[ggbnsans:=fsolve(ggbnsans,ggbvars[0])],[ggbnsans:=when(type(ggbnsans)==DOM_LIST,ggbnsans,[ggbnsans])],ggbnsans][3])],"
+ "ggbnsans][2])");
p("NSolutions.2",
"ggbsort([[ggbnsans:=fsolve((%%0),%%1)],when(type(ggbnsans)==DOM_LIST,ggbnsans,[ggbnsans])][1])");
// numer(), denom() cancel down first so use getNum, getDen
// a/b encoded as a*(1/b)
// factor needed for eg a/b + c/d
// need to use %0 to avoid auto-simplifying eg
// Numerator[((x+1)*x)/(x+1)]
// || length(%0) > 2 is for Numerator[((x+1)*x)/(x+1)] which Giac stores
// as a product of *3* things
p("Numerator.1",
"[[ggbnumerans:=%0]," + "when((%0)[0]=='inv', getNum(%0), "
+ "when((%0)[0]=='*', "
+ "when((%0)[2][0]=='inv' || length(%0) > 2, getNum(%0), getNum(factor(ggbnumerans))),"
+ "getNum(factor(ggbnumerans)) )" + ")][1]");
p("Numeric.1",
"[[ggbnumans:=%0],when(dim(lname(ggbnumans))==0 || count_eq(unicode0176u,lname(ggbnumans))>0,"
+
// normal() so that Numeric(x + x/2) works
// check for unicode0176u so that
// Numeric[acos((-11.4^2+5.8^2+7.2^2)/(2 5.8 7.2))]
// is better when returning degrees from inverse trig
"evalf(ggbnumans)" + "," +
// #4537
"normal(evalf(regroup(ggbnumans)))" + ")][1]");
p("Numeric.2",
"[[ggbnumans:=%0],when(dim(lname(ggbnumans))==0 || lname(ggbnumans)==[unicode0176u],"
+
// normal() so that Numeric(x + x/2) works
// check for unicode0176u so that
// Numeric[acos((-11.4^2+5.8^2+7.2^2)/(2 5.8 7.2))]
// is better when returning degrees from inverse trig
"evalf(ggbnumans,%1)" + "," +
// #4537
"normal(evalf(regroup(ggbnumans),%1))" + ")][1]");
// using sub twice in opposite directions seems to fix #2198, though
// it's sort of magic
// with_sqrt(0) to factor over rationals
p("PartialFractions.1", "partfrac(%0)");
p("PartialFractions.2", "partfrac(%0,%1)");
p("Pascal.4",
"[[[ggbpasarg0:=%0],[ggbpasarg1:=%1],[ggbpasarg2:=%2]],if %3==true then Beta(ggbpasarg0,1+floor(ggbpasarg2),ggbpasarg1,1) else (1-(%1))^(ggbpasarg2)*(ggbpasarg1)^(ggbpasarg0)*binomial(ggbpasarg0+ggbpasarg2-1,ggbpasarg0-1) fi][1]");
p("Plane.1", "plane(%0)");
p("Poisson.3", "if %2==true then "
+ "exp(-(%0))*sum ((%0)^k/k!,k,0,floor(%1)) "
+ "else normal((%0)^(%1)/factorial(floor(%1))*exp(-%0)) fi");
p("Polynomial.N", "[[[ggbpolans:=0/0], [ggbvar:=x], [ggbinput:=%], "
// DOM_IDENT: something like x or y
+ "when(type(ggbinput)==DOM_LIST && type(ggbinput[1]) != DOM_IDENT,"
// eg Polynomial[{(1, 1), (2, 3)}]
// eg Polynomial[(1, 1), (2, 3)]
// eg Polynomial[{(1, 1), (2, 3), (3, 6)}]
// eg Polynomial[(1, 1), (2, 3), (3, 6)]
+ "[[xvals := [seq(xcoord(ggbinput[j]),j=0..size(ggbinput)-1)]], [yvals := [seq(ycoord(ggbinput[j]),j=0..size(ggbinput)-1)]], [ggbpolans := normal(lagrange(xvals,yvals,x))]]"
+ ","
// eg Polynomial[x^2+a x + b x +c]
// eg Polynomial[y^2+a y + b y +c,y]
+ "[[ggbinput:=when(type(ggbinput)==DOM_LIST,[[ggbvar:=ggbinput[1]],coeffs(ggbinput[0],ggbinput[1])][1],coeffs(ggbinput,x))], "
+ "[ggbpolans:=add(seq(ggbinput[j]*ggbvar^(size(ggbinput)-1-j),j=0..size(ggbinput)-1))]]"
+ ")],ggbpolans][1]");
p("PreviousPrime.1",
"[[ggbpparg0:=%0],if (ggbpparg0 > 2) then prevprime(ggbpparg0) else 0/0 fi][1]");
p("PrimeFactors.1", "ifactors(%0)");
// normal() makes sure answer is expanded
// TODO: do we want this, or do it in a more general way
p("Product.1", "normal(product(%0))");
p("Product.4", "normal(product(%0,%1,%2,%3))");
// p("Prog.1","<<%0>>");
// p("Prog.2","<<begin scalar %0; return %1 end>>");
p("Random.2",
"[[ggbranarg0:=%0],ggbranarg0+rand(%1-(ggbranarg0)+1)][1]"); // "RandomBetween"
p("RandomBinomial.2", "binomial_icdf(%0,%1,rand(0,1))");
p("RandomElement.1", "rand(1,%0)[0]");
p("RandomPoisson.1", "poisson_icdf(%0,rand(0,1))"); // could also make
// the product of
// rand(0,1) until
// less than
// exp(-%0)
p("RandomNormal.2", "randnorm(%0,%1)");
p("RandomPolynomial.3", "randpoly(%0,x,%1,%2)");
p("RandomPolynomial.4", "randpoly(%1,%0,%2,%3)");
p("Rationalize.1",
"[[ggbratarg0:=%0],if type(ggbratarg0)==DOM_RAT then ggbratarg0 else normal(exact(ggbratarg0)) fi][1]");
p("Reverse.1", "revlist(%0)");
p("RightSide.1",
"[[ggbrightarg0:=%0],when(type(ggbrightarg0)==DOM_LIST,map(ggbrightarg0,"
+ "t->when(t[0] == '=',right(t),?)),"
// RightSide only defined for equations
// see GGB-1116
+ "when ((ggbrightarg0)[0] == '=',"
+ "right(ggbrightarg0),?))][1]");
p("RightSide.2", "[[ggbrightarg0:=%0],"
+ "when(ggbrightarg0[%1-1][0] == '=',right(ggbrightarg0[%1-1]),?)][1]");
p("ReducedRowEchelonForm.1", "rref(%0)");
p("Sample.2", "flatten1(seq(rand(1,%0),j,1,%1))");
p("Sample.3",
"[[[ggbsamarg0:=%0],[ggbsamarg1:=%1]],if %2==true then flatten1(seq(rand(1,ggbsamarg0),j,1,ggbsamarg1)) else rand(ggbsamarg1,ggbsamarg0) fi][1]");
p("SampleVariance.1",
" [[ggbsvans:=%0],[ggbsvans:=normal(variance(ggbsvans)*size(ggbsvans)/(size(ggbsvans)-1))],ggbsvans][2]");
p("SampleSD.1", "normal(stddevp(%0))");
p("Sequence.1", "when(round(%0)<1,{},seq(1,round(%0),1))");
p("Sequence.2", "seq(round(%0),round(%1),1)");
p("Sequence.4", "seq(%0,%1,%2,%3)");
p("Sequence.5", "seq(%0,%1,%2,%3,%4)");
// strings are handled differently with giac.js
// so we need to return 10^10 as 10^{10}
// so LaTeX displays the power correctly
// default 15, like Input Bar version
p("ScientificText.1",
" [[[ggbstinput:=%0],[ggbstans:=?],[ggbstabsans:=abs(ggbstinput)],[ggbstpower:=floor(log10(ggbstinput))],"
+ "[ggbstans:=evalf(ggbstinput / 10^ggbstpower, 15) + \" * 10^ \" + ggbstpower ]],when(ggbstinput==0,0,ggbstans)][1]");
p("ScientificText.2",
" [[[ggbstinput:=%0],[ggbstans:=?],[ggbstabsans:=abs(ggbstinput)],[ggbstpower:=floor(log10(ggbstinput))],"
+ "[ggbstans:=evalf(ggbstinput / 10^ggbstpower, %1) + \" * 10^ \" + ggbstpower]],when(ggbstinput==0,0,ggbstans)][1]");
p("SD.1", "normal(stddev(%0))");
// removed, Shuffle[{1,2}] kills Giac
p("Shuffle.1", "randperm(%0)");
// regroup for r*r^n
// tlin() removed, see #3956
// texpand() added for Simplify[exp(x)/exp(x+1)]
// normal needed for Simplify[sqrt(2)*sqrt(5)]
p("Simplify.1", "normal(simplify(regroup(texpand(%0))))");
p("Solutions.1", "ggbsort(normal(zeros(%0,x)))");
p("Solutions.2", "ggbsort(normal(zeros(%0,%1)))");
// Root.1 and Solve.1 should be the same
String root1 = "ggbsort(normal([op(solve(%0))]))";
p("Root.1", root1);
p("Solve.1", root1);
p("Solve.2",
// Solve[<Equation in x>,<assumption>]
// GGB-134
// hack needed for GGB-618
// aa(t) has symbolic type
"when ( type(%0) == DOM_SYMBOLIC && type(%1) == DOM_SYMBOLIC && (%1)[0] != 'of' , (assume(%1),solve(%0,x)) [size(assume(%1),solve(%0,x))-1] , "
// if input equation was only x, interpret as x=0
+ "when ( type(%0) == DOM_IDENT && type(%1) == DOM_SYMBOLIC && %0 == 'x', (assume(%1),solve(%0=0,x))[size(assume(%1),solve(%0=0,x))-1] ,"
+ "when ( size(%1) == 1,"
+ "flatten1(ggbsort(normal([op(solve(%0,%1))]))),"
+ "ggbsort(normal([op(solve(%0,%1))])) ) ) )");
// solve with assumptions
p("Solve.3",
// accepted input
// Solve[<equation>,<variable>,<assumption>]
// or Solve[<list of equations>,<list of variable>,<list of
// assumptions>]
"when( (type(%0) == DOM_SYMBOLIC || type(%0) == DOM_LIST) && (type(%1) == DOM_IDENT || type(%1) == DOM_LIST) , "
+ "(assume(%2),solve(%0,%1))[size(assume(%2),solve(%0,%1))-1] , ? )");
p("SolveODE.1",
"when((%0)[0]=='=',"
// case the equation contains only y and other variable
// as x, by default use for variable list y, x
// #5099
+ " when (size(lname(%0) intersect [x]) == 0 && size(lname(%0) intersect [y]) == 1 && size(lname(%0) minus [y]) > 0,normal(map(desolve(%0,x,y),x->y=x)[0]),normal(map(desolve(%0),x->y=x)[0]))"
+ ","
// add y'= if it's missing
+ "normal(map(desolve(y'=%0),x->y=x)[0])" + ")");
// goes through 1 point
// SolveODE[y''=x, (1,1)]
// goes through 1 point, y'= missing
// SolveODE[x,(1, 1)]
// goes through 2 points
// SolveODE[y''=x, {(1,1),(2,2)}]
// can't do [solveodearg0:=%0] as y' is immediately simplified to 1
p("SolveODE.2", "" + "normal(y=when(type(%1)==DOM_LIST," +
// list of 2 points
"desolve([%0,y(xcoord(%1[0]))=ycoord(%1[0]),y(xcoord(%1[1]))=ycoord(%1[1])],x,y)"
+ "," +
// one point
"desolve(when((%0)[0]=='=',%0,y'=%0),x,y,%1)" + ")" + ""
+ "[0])");
p("SolveODEPoint.2", "" + "normal(y=" +
// list of 2 points
// one point
"desolve(y'=%0,x,y,%1)[0])");
p("SolveODE.3",
"when((%0)[0]=='=',"
+ "normal(map(desolve(%0,%2,%1),(type(%1)==DOM_IDENT)?(x->%1=x):(x->y=x))[0])"
+ ","
// add y'= if it's missing
+ "normal(map(desolve(y'=%0,%2,%1),(type(%1)==DOM_IDENT)?(x->%1=x):(x->y=x))[0])"
+ ")");
p("SolveODE.4", "when((%0)[0]=='=',"
+ "normal(map(desolve(%0,%2,%1,%3),x->%1=x)[0])" + ","
// add y'= if it's missing
+ "normal(map(desolve(y'=%0,%2,%1,%3),x->%1=x)[0])" + ")");
p("SolveODE.5", // SolveODE[y''=x,y,x,A,{B}]
"normal(map(desolve(%0,%2,%1,%3,%4),x->%1=x)[0])");
p("Substitute.2", "subst(%0,%1)");
p("Substitute.3", "subst(%0,%1,%2)");
// p("SubstituteParallel.2","if hold!!=0 then sub(%1,%0) else
// sub(%1,!*hold(%0))");
p("Sum.1",
"[[ggbsumarg1:=%0],when ( when(size(ggbsumarg1)>0,ggbsumarg1[0],1)[0] == 'pnt' ,"
+ "point(sum(map(ggbsumarg1,t->makevector(xcoord(t))))[0],sum(map(ggbsumarg1,t->makevector(ycoord(t))))[0]) ,"
+ "sum(ggbsumarg1))][1]");
// remove normal from Sum, otherwise
// Sum[1/n*sqrt(1-(k/n)^2),k,1,n]
// Sum[1/10*sqrt(1-(k/10)^2),k,1,10]
// don't work
// Sum[Sum[x+2y, x, 1, 3], y, 2, 4]
// expand added for Sum[2+3(n-1),n,1,n]
p("Sum.4",
"expand(subst(sum(subst(%0,%1,ggbsumvar@1),ggbsumvar@1,%2,%3), ggbsumvar@1, %1))");
// svd = singular value decomposition
// svd(M)=[U,S,V]
// such that M=U*diag(S)*tran(V)
// some messing around needed as Giac automatically completes U, V to
// orthogonal matrices
p("SVD.1",
"[[[svdarg:=%0], [svgdim:=dim(%0)], [svdresult:=svd(svdarg)],], {trn(trn(svdresult[0])[0..svgdim[1]-1]), diag(svdresult[1]), trn(trn(svdresult[2])[0..svgdim[0]-1])}][1]");
// GeoGebra counts elements from 1, giac from 0
// p("Take.3", "%0[%1-1..%2-1]");
p("Take.2",
"[[[ggbtakearg0:=%0],[ggbtakearg1:=%1]],ggbtakearg0[ggbtakearg1-1..length(ggbtakearg0)]][1]");
p("Take.3",
"[[[ggbtakearg0:=%0],[ggbtakearg1:=%1],[ggbtakearg2:=%2]],ggbtakearg0[ggbtakearg1-1..ggbtakearg2-1]][1]");
p("TaylorSeries.3", "convert(series(%0,x,%1,%2),polynom)");
p("TaylorSeries.4", "convert(series(%0,%1,%2,%3),polynom)");
p("TDistribution.2", "student_cdf(%0,%1)");
// alternative for exact calculations, but
// Numeric[TDistribution[4,2],15] doesn't work with this
// "1/2 + (Beta(%0 / 2, 1/2, 1, 1) - Beta(%0 / 2, 1/2, %0 / (%0 + (%1)^2
// ) ,1) )* sign(%1) / 2");
p("ToComplex.1",
"[[ggbtcans:=?],[ggbtcans:=%0],[ggbtype:=type(evalf(ggbtcans))],"
+
// ToComplex[3.1]
"when(ggbtype==DOM_INT || ggbtype==DOM_FLOAT,ggbtcans,"
+
// ToComplex[(3,4)]
"when(ggbtcans[0]=='pnt',xcoord(%0)+i*ycoord(%0)," +
// ToComplex[ln(i)], ToComplex[a]
"real(ggbtcans)+i*im(ggbtcans)" + "))][3]");
p("ToExponential.1", "rectangular2polar(%0)");
p("ToPolar.1",
"([[ggbtpans:=%0],[ggbtpans:=polar_coordinates(ggbtpans)],[ggbtpans:=convert([ggb_ang(ggbtpans[0],ggbtpans[1])],25)],ggbtpans])[3]");
p("ToPoint.1", "point(convert(coordinates(%0),25))");
// if (app.has(Feature.CAS_TRANSLATE_COMMAND)) {
p("Translate.2",
"[[[ggbtrsarg0:=%0] , [ggbtrsarg1:=%1]] , "
// invalid case: translate vector by vector
+ "when ( subtype(ggbtrsarg0) == 27 && subtype(ggbtrsarg1) == 27,"
+ "?, "
// translate vector by point -> return vector
+ "when ( subtype(ggbtrsarg0) == 27 && (ggbtrsarg1)[0] == 'pnt',"
+ "ggbtrsarg0,"
// translate point about vector
+ "when ( (ggbtrsarg0)[0] == 'pnt' , "
// translate 2d point
+ "when ( !is_3dpoint(ggbtrsarg0) ,"
// vector as point
+ "when ( (ggbtrsarg1)[0] == 'pnt' ,"
+ "translation(vector(ggbtrsarg1),ggbtrsarg0) ,"
+ "translation(ggbtrsarg1,ggbtrsarg0) ),"
// translate 3d point
+ "when( (ggbtrsarg1)[0] == 'pnt',"
// vector as point
+ "point(xcoord(translation(vector(ggbtrsarg1),ggbtrsarg0))[0],"
+ "xcoord(translation(vector(ggbtrsarg1),ggbtrsarg0))[1], "
+ "xcoord(translation(vector(ggbtrsarg1),ggbtrsarg0))[2]),"
+ "point(xcoord(translation(ggbtrsarg1,ggbtrsarg0))[0],"
+ "xcoord(translation(ggbtrsarg1,ggbtrsarg0))[1], "
+ "xcoord(translation(ggbtrsarg1,ggbtrsarg0))[2]) ) ),"
// translate object(line, circle, ellipse)
+ "when ( grad(ggbtrsarg0,y) <> 0,"
+ " regroup(equation(subs(ggbtrsarg0,x=x-xcoord(ggbtrsarg1),y=y-ycoord(ggbtrsarg1)))),"
// handle special case: no y in equation
+ "regroup(equation(subs(ggbtrsarg0,x=x-xcoord(ggbtrsarg1))))+ycoord(ggbtrsarg1) )"
+ " ) ) ) ][1]");
// }
p("Transpose.1", "transpose(%0)");
// http://reduce-algebra.com/docs/trigsimp.pdf
// possible Giac commands we can use:
// halftan, tan2sincos2, tan2cossin2, sincos, trigtan, trigsin, trigcos
// cos2sintan, sin2costan, tan2sincos, trigexpand, tlin, tcollect,
// trig2exp, exp2trig
// eg tlin(halftan(csc(x) - cot(x) + csc(y) - cot(y))) ->
// tan(x/2)+tan(y/2)
p("TrigExpand.1", "tan2sincos(trigexpand(%0))");
p("TrigExpand.2",
"[[ggbtrigarg0:=%0],when((%1)[0]=='tan', trigexpand(ggbtrigarg0),tan2sincos(trigexpand(ggbtrigarg0)))][1]");
// subst(trigexpand(subst(sin(x),solve(tmpvar=x/2,lname(sin(x)))),tmpvar=x/2)
// gives 2*cos(x/2)*sin(x/2)
p("TrigExpand.3",
"[[[ggbtrigarg0:=%0],[ggbtrigarg2:=%2]]," + "when(%1==tan(x)," +
// if %1=tan(x), assume %2=x/2
"tlin(halftan(ggbtrigarg0))" + ","
+ "subst(trigexpand(subst(ggbtrigarg0,solve(ggbtmp=ggbtrigarg2,lname(ggbtrigarg0)))),ggbtmp=ggbtrigarg2)"
+ ")][1]");
// subst(subst(trigexpand(subst(subst((sin(x))+(sin(y)),solve(tmpvar=(x)/(2),lname((sin(x))+(sin(y)))
// )),solve(tmpvar2=(y)/(2),lname((sin(x))+(sin(y)))
// ))),tmpvar=x/2),tmpvar2=y/2)
// 2*cos(x/2)*sin(x/2)+2*cos(y/2)*sin(y/2)
p("TrigExpand.4",
"[[[ggbtrigarg0:=%0],[ggbtrigarg2:=%2],[ggbtrigarg3:=%3]],"
+ "when(%1==tan(x)," +
// if %1=tan(x), assume %2=x/2, %3=y/2
"tlin(halftan(ggbtrigarg0))" + ","
+ "subst(subst(trigexpand(subst(subst(ggbtrigarg0,solve(tmpvar=ggbtrigarg2,lname(ggbtrigarg0))),solve(tmpvar2=ggbtrigarg3,lname(ggbtrigarg0)))),tmpvar=ggbtrigarg2),tmpvar2=ggbtrigarg3)"
+ ")][1]");
// calculate trigsin, trigcos, trigtan and check which is shortest (as a
// string)
p("TrigSimplify.1",
"[[[ggbtrigarg:=%0], [ggbsin:=trigsin(ggbtrigarg)], [ggbcos:=trigcos(ggbtrigarg)], [ggbtan:=trigtan(ggbtrigarg)], "
+ "[ggbsinlen:=length(\"\"+ggbsin)],[ggbcoslen:=length(\"\"+ggbcos)],[ggbtanlen:=length(\"\"+ggbtan)]],"
+ "when(ggbsinlen<=ggbcoslen && ggbsinlen<=ggbtanlen,ggbsin,when(ggbcoslen<=ggbtanlen,ggbcos,ggbtan))][1]");
// try with and without tan2sincos(), tcollectsin() and check which i //
// eg TrigCombine[(tan(x) + tan(2x)) / (1 - tan(x) tan(2x))]
p("TrigCombine.1",
"[[[ggbtrigarg:=%0], [ggbsin:=tcollectsin(normal(ggbtrigarg))], [ggbcos:=tcollect(normal(ggbtrigarg))], [ggbtan:=tcollect(normal(tan2sincos(ggbtrigarg)))], "
+ "[ggbsinlen:=length(\"\"+ggbsin)],[ggbcoslen:=length(\"\"+ggbcos)],[ggbtanlen:=length(\"\"+ggbtan)]],"
+ "when(ggbcoslen<=ggbsinlen && ggbcoslen<=ggbtanlen,ggbcos,when(ggbsinlen<=ggbtanlen,ggbsin,ggbtan))][1]");
// eg TrigCombine[sin(x)+cos(x),sin(x)]
p("TrigCombine.2",
"[[[ggbtrigarg0:=%0],[ggbtrigarg1:=%1]],when(ggbtrigarg1[0]=='sin',tcollectsin(normal(ggbtrigarg0)),when(ggbtrigarg1[0]=='tan',tcollect(normal(tan2sincos(ggbtrigarg0))),tcollect(normal(ggbtrigarg0))))][1]");
p("Union.2", "(%0) union (%1)");
p("Unique.1", "[op(set[op(%0)])]");
p("Variance.1", "normal(variance(%0))");
p("Weibull.3", "1-exp(-((%2)/(%1))^(%0))");
p("Zipf.4", // %1=exponent
"[[[ggbzipfarg0:=%0],[ggbzipfarg1:=%1],[ggbzipfarg2:=%2]],if %3==true then harmonic(ggbzipfarg1,ggbzipfarg2)/harmonic(ggbzipfarg1,ggbzipfarg0) else 1/((ggbzipfarg2)^ggbzipfarg1*harmonic(ggbzipfarg1,ggbzipfarg0)) fi][1]");
// TODO check if it's easier to implement with giac's zip command
p("Zip.N",
"[[ggbzipans(l):=begin local len,res,sbl,xpr,k,j;xpr:=l[0];len:=length(l[2]);res:={};"
+ "for k from 4 to length(l)-1 step +2 do len:=min(len,length(l[k])); od;"
+ "for k from 0 to len-1 do sbl:={};for j from 2 to length(l)-1 step +2 do"
+ " sbl:=append(sbl, l[j-1]=l[j][k]);od;res:=append(res, subst(xpr,sbl));od; res; end],ggbzipans(%)][1]");
// SolveCubic[x^3+3x^2+x-1]
// SolveCubic[x^3+3x^2+x-2]
// SolveCubic[x^3+3x^2+x-3]
// SolveCubic[x^3 + 6x^2 - 7*x - 2]
// x^3 - 6x^2 - 7x + 9
// check with CSolve first, eg
// f(x) = x^3 - 9x^2 - 2x + 8
// adapted from xcas example by Bernard Parisse
p("SolveCubic.1",
"[" + "[j:=exp(2*i*pi/3)]," + "[ggbcub:=%0],"
+ "[V:=symb2poly(when(ggbcub[0]=='=',left(ggbcub)-right(ggbcub),ggbcub),x)],"
+ "[n:=size(V)]," +
// if (n!=4){
// throw(afficher(P)+" n'est pas de degre 3");
// }
// Reduction de l'equation
"[V:=V/V[0]]," + "[b:=V[1]]," + "[V:=ptayl(V,-b/3)],"
+ "[p:=V[2]]," + "[q:=V[3]]," +
// on est ramen x^3+p*x+q=0
// x=u+v -> u^3+v^3+(3uv+p)(u+v)+q=0
// On pose uv=-p/3 donc u^3+v^3=-q et u^3 et v^3 sont
// solutions
// de u^3 v^3 = -p^3/27 et u^3+v^3=-q
// donc de x^2+q*x-p^3/27=0
"[d:=q^2/4+p^3/27]," +
// if (d==0){
// // racine double
// return solve(P,x);
// }
"[d:=sqrt(d)]," + "[u:=(-q/2+d)^(1/3)],"
+ "[v:=-p/3/u]," + "[x1:=u+v-b/3],"
+ "[x2:=u*j+v*conj(j)-b/3],"
+ "[x3:=u*conj(j)+v*j-b/3],"
+ "[x1s:=regroup(normal(x1))],"
+ "[x2s:=regroup(normal(x2))],"
+ "[x3s:=regroup(normal(x3))],"
// for debugging
// + "[p,q,d,u,v,x1,x2,x3]"
// SolveCubic[x^3+1] -> u=0, v=?
+ "when(d==0 || u==0, csolve(ggbcub,x), [x1s,x2s,x3s])"
+ "][19]");
// SolveQuartic[2x^4+3x^3+x^2+1]
// SolveQuartic[x^4+6x^2-60x+36] approx = {(-1.872136644123) -
// (3.810135336798 * <complexi>), (-1.872136644123) + (3.810135336798 *
// <complexi>),
// 0.6443988642267, 3.099874424019}
// SolveQuartic[3x^4 + 6x^3 - 123x^2 - 126x + 1080] = {(-6), (-4), 3, 5}
// SolveQuartic[x^(4) - (10 * x^(3)) + (35 * x^(2)) - (50 * x) + 24] =
// {1, 3, 2, 4}
// SolveQuartic[x^4 + 2x^3 - 41x^2 - 42x + 360] = {(-6), (-4), 3, 5}
// SolveQuartic[ x^4 + 2x^2 + 6sqrt(10) x + 1] approx
// {(-2.396488591753), (-0.05300115102973), 1.224744871392 -
// (2.524476846043 * <complexi>), 1.224744871392 + (2.524476846043 *
// <complexi>)}
// SolveQuartic[x^4 + x^3 + x + 1] = {(-1), (-1), (((-<complexi>) *
// sqrt(3)) + 1)
// / 2, ((<complexi> * sqrt(3)) + 1) / 2}
// SolveQuartic[x^(4) - (4 * x^(3)) + (6 * x^(2)) - (4 * x) + 1] = {1}
// 3 repeated roots, S=0, SolveQuartic[ x^4 - 5x^3 + 9x^2 - 7x + 2 ] =
// {2,1}
// SolveQuartic[x^(4) - (2 * x^(3)) - (7 * x^(2)) + (16 * x) - 5] =
// ((x^(2) - (3 * x) + 1) * (x^(2) + x - 5))
// http://en.wikipedia.org/wiki/Quartic_function
// GGB-1635
if (app.has(Feature.SOLVE_QUARTIC)) {
p("SolveQuartic.1", "[" + "[ggbsqans:={}]," + "[ggbfun:=%0],"
+ "[ggbcoeffs:=coeffs(ggbfun)]," + "[a:=ggbcoeffs[0]],"
+ "[b:=ggbcoeffs[1]]," + "[c:=ggbcoeffs[2]],"
// for checking, but unnecessary
+ "[d:=ggbcoeffs[3]]," + "[ee:=ggbcoeffs[4]]," +
"[delta:=256*a^3*ee^3-192*a^2*b*d*ee^2-128*a^2*c^2*ee^2+144*a^2*c*d^2*ee-27*a^2*d^4+144*a*b^2*c*ee^2-6*a*b^2*d^2*ee-80*a*b*c^2*d*ee+18*a*b*c*d^3+16*a*c^4*ee-4*a*c^3*d^2-27*b^4*ee^2+18*b^3*c*d*ee-4*b^3*d^3-4*b^2*c^3*ee+b^2*c^2*d^2],"
+ "[p:=(8*a*c-3*b*b)/(8*a*a)],"
+ "[q:=(b^3-4*a*b*c+8*a^2*d)/(8*a^3)],"
+ "[delta0:=c^2-3*b*d+12*a*ee]," + // OK
"[delta1:=2*c^3-9*b*c*d+27*b^2*ee+27*a*d^2-72*a*c*ee]," + // OK
// giac's solve should give exact in this case
"if (delta0 == 0 && delta1 == 0) then"
+ " ggbsqans:=zeros(ggbfun) else " +
" [" + "[minusdelta27:=delta1^2-4*delta0^3]," +
// use surd rather than cbrt so that simplify cbrt(27) works
"[Q:=simplify(surd((delta1 + when(delta0==0, delta1, sqrt(minusdelta27)))/2,3))],"
+ // find all 3 cube-roots
"[Qzeros:=czeros(x^3=(delta1 + when(delta0==0, delta1, sqrt(minusdelta27)))/2)],"
+ // czeros can return an empty list eg czeros(x^(3) = (1150
// +
// ((180 * i) * sqrt(35))) / 2) // from
// SolveQuartic[x^(4) -
// (2 * x^(3)) - (7 * x^(2)) + (16 * x) - 5]
"[Qzeros:=when(length(Qzeros)==0,{cbrt((delta1 + when(delta0==0, delta1, sqrt(minusdelta27)))/2)},Qzeros)],"
+ "[Q:=Qzeros[0]],"
+ "[Q1:=when(length(Qzeros) > 1,Qzeros[1],Qzeros[0])],"
+ "[Q2:=when(length(Qzeros) > 2,Qzeros[2],Qzeros[0])]," +
// pick a cube-root to make S non-zero always possible
// unless
// quartic is in form (x+a)^4
"[S:=sqrt(-2*p/3+(Q+delta0/Q)/(3*a))/2],"
+ "[S:=when(S!=0,S,sqrt(-2*p/3+(Q1+delta0/Q1)/(3*a))/2)],"
+ "[S:=when(S!=0,S,sqrt(-2*p/3+(Q2+delta0/Q2)/(3*a))/2)]," +
// could use these for delta > 0 ie minusdelta27 < 0
// "[phi:=acos(delta1/2/sqrt(delta0^3))],"+
// "[Salt:=sqrt(-2*p/3+2/(3*a)*sqrt(delta0)*cos(phi/3))/2],"+
"[ggbsqans:={simplify(-b/(4*a)-S-sqrt(-4*S^2-2*p+q/S)/2),simplify(-b/(4*a)-S+sqrt(-4*S^2-2*p+q/S)/2),simplify(-b/(4*a)+S-sqrt(-4*S^2-2*p-q/S)/2),simplify(-b/(4*a)+S+sqrt(-4*S^2-2*p-q/S)/2)}]"
+ "]" + "fi" +
// ")]" +
" ,ggbsqans][13][10][0]");
}
// Experimental Geometry commands. Giac only
p("Radius.1", "normal(regroup(radius(%0)))");
p("Center.1", "coordinates(center(%0))");
p("Midpoint.2", "normal(regroup(coordinates(midpoint(%0,%1))))");
// center-point: point(%0),point(%1)
// or center-radius: point(%0),%1
// regroup r*r -> r^2 without multiplying out
// circle(2*(%0)-(%1),%1) to convert centre,point -> points on diameter
p("Circle.2",
"[[[ggbcirarg0:=%0],[ggbcirarg1:=%1]],regroup(equation(when(ggbcirarg1[0]=='pnt',circle(2*(ggbcirarg0)-(ggbcirarg1),ggbcirarg1),circle(ggbcirarg0,ggbcirarg1))))][1]");
p("Area.1", "normal(regroup(area(circle(%0))))");
p("Circumference.1", "normal(regroup(perimeter(%0)))");
p("LineBisector.2", "equation(perpen_bisector(%0,%1))");
p("AngularBisector.2",
"[[ggbabarg0:=%0],[ggbabarg1:=%1],[B:=inter(ggbabarg0,ggbabarg1)],[eqa:=equation(ggbabarg0)],[eqb:=equation(ggbabarg1)],"
+ "[uva:=convert([unitV(coeff(left(eqa)-right(eqa),y,1),-coeff(left(eqa)-right(eqa),x,1))],25)],"
+ "[uvb:=convert([unitV(coeff(left(eqb)-right(eqb),y,1),-coeff(left(eqb)-right(eqb),x,1))],25)],"
// length(B)==0 for parallel lines
// TODO: document when uva==uvb
+ "when(uva==uvb || length(B) == 0,[?,?],[equation(line(B[0],B[0]+uva-uvb)),equation(line(B[0],B[0]+uva+uvb))])][7]");
p("AngularBisector.3", "equation(bisector(%1,%0,%2))");
p("Angle.1", "normal(regroup((%0) *180 / pi)) * unicode0176u");
// point(xcoord(ggbangarg0),ycoord(ggbangarg0),zcoord(ggbangarg0))
// so we can mix 2d and 3d points
p("Angle.2", "[[[ggbangarg0:=%0], [ggbangarg1:=%1]], "
// handle special case function as single variable
// e.g. Angle[x,3-x]
+ "when ( type(ggbangarg0) == DOM_IDENT || type(ggbangarg1) == DOM_IDENT ,"
+ "normal(regroup(angle(point(0,0,0) ,"
+ "point(coeff(ggbangarg0,x,1),1," + "coeff(ggbangarg0,z,1)) ,"
+ "point(coeff(ggbangarg1,x,1),1,coeff(ggbangarg1,z,1))))),"
// case angle between planes
+ "when( string(xcoord(ggbangarg0[1])) == string(hyperplan) && string(xcoord(ggbangarg1[1])) == string(hyperplan) , "
+ "normal(regroup(angle(point(0,0,0),"
+ "point( ggbangarg0[1][1][0] , ggbangarg0[1][1][1] , ggbangarg0[1][1][2]),"
+ "point( ggbangarg1[1][1][0] , ggbangarg1[1][1][1] , ggbangarg1[1][1][2]) ))),"
// line defined with command and plane defined with
// command
+ "when ( xcoord(ggbangarg0) == string(X) && string(xcoord(ggbangarg1[1])) == string(hyperplan) ,"
+ "normal(regroup(angle(point(0,0,0),"
+ "point( coeff(expr(ggbangarg0)[0][2],\u03BB,1) , coeff(expr(ggbangarg0)[1][2],\u03BB,1) , coeff(expr(ggbangarg0)[2][2],\u03BB,1) ),"
+ "point( ggbangarg1[1][1][0] , ggbangarg1[1][1][1] , ggbangarg1[1][1][2]) ))) ,"
// line defined from inputBar and plane defined with
// command
+ "when( (xcoord(ggbangarg0))[0] == '=' && string((xcoord(ggbangarg0))[1]) == string(X) && string(xcoord(ggbangarg1[1])) == string(hyperplan),"
+ "normal(regroup(angle(point(0,0,0),"
+ "point((ggbangarg0[2][2][2])[2][0],(ggbangarg0[2][2][2])[2][1],(ggbangarg0[2][2][2])[2][2]),"
+ "point((ggbangarg1)[1][1][0],(ggbangarg1)[1][1][1],(ggbangarg1)[1][1][2]) ))),"
// functions without y or f(x)
// e.g. Angle[x+1,-x+3]
+ "when ( (ggbangarg0)[0] <> '=' && (ggbangarg0)[0] <> 'pnt' && "
+ "xcoord(ggbangarg0) <> string(X) && (xcoord(ggbangarg0))[0] <> '=' && "
+ "(ggbangarg1)[0] <> '=' && (ggbangarg1)[0] <> 'pnt' &&"
+ " xcoord(ggbangarg1) <> string(X) && (xcoord(ggbangarg1))[0] <> '=' && "
+ "subtype(ggbangarg0) <> 27 && subtype(ggbangarg1) <> 27,"
+ "normal(regroup(angle(point(0,0,0) ,"
+ "point(coeff(ggbangarg0,x,1),1," + "coeff(ggbangarg0,z,1)) ,"
+ "point(coeff(ggbangarg1,x,1),1,coeff(ggbangarg1,z,1))))),"
// case lines defined as functions
+ "when ( (ggbangarg0)[0] == '=' && (ggbangarg0)[1][0] == 'of' && (ggbangarg0)[1][2] == 'x' &&"
+ "(ggbangarg1)[0] == '=' && (ggbangarg1)[1][0] == 'of' && (ggbangarg1)[1][2] == 'x' , "
+ " normal(regroup(angle(point(0,0,0),"
+ "point(xcoord(ggbangarg0),1,zcoord(ggbangarg0)),"
+ "point(xcoord(ggbangarg1),1,zcoord(ggbangarg1)) ))),"
// case line from inputBar and plane by lin. equation
+ "when( (xcoord(ggbangarg0))[0] == '=' && string((xcoord(ggbangarg0))[1]) == string(X) && type(xcoord(ggbangarg1)) == DOM_INT,"
+ "normal(regroup(angle(point(0,0,0),"
+ "point((ggbangarg0[2][2][2])[2][0],(ggbangarg0[2][2][2])[2][1],(ggbangarg0[2][2][2])[2][2]),"
+ "point(xcoord(ggbangarg1),ycoord(ggbangarg1),zcoord(ggbangarg1)) ))), "
// case line or plane defined by linear equation
// or points or vectors (GGB-988)
+ "when( ( type(xcoord(ggbangarg0)) == DOM_INT || (ggbangarg0)[0] == 'pnt' || subtype(ggbangarg0) == 27) && ( type(xcoord(ggbangarg1)) == DOM_INT || (ggbangarg1)[0] == 'pnt' || subtype(ggbangarg1) == 27),"
+ "normal(regroup(angle(point(0,0,0),point(xcoord(ggbangarg0),ycoord(ggbangarg0),zcoord(ggbangarg0)),point(xcoord(ggbangarg1),ycoord(ggbangarg1),zcoord(ggbangarg1))))),"
// case 3D lines defined in this command
+ "when ( xcoord(ggbangarg0) == string(X) && xcoord(ggbangarg1) == string(X) ,"
+ "normal(regroup(angle(point(0,0,0),"
+ "point( coeff(expr(ggbangarg0)[0][2],\u03BB,1) , coeff(expr(ggbangarg0)[1][2],\u03BB,1) , coeff(expr(ggbangarg0)[2][2],\u03BB,1) ),"
+ "point( coeff(expr(ggbangarg1)[0][2],\u03BB,1) , coeff(expr(ggbangarg1)[1][2],\u03BB,1) , coeff(expr(ggbangarg1)[2][2],\u03BB,1) ) ))) ,"
// case 3D lines defined from inputBar
+ "when( (xcoord(ggbangarg0))[0] == '=' && string((xcoord(ggbangarg0))[1]) == string(X) && (xcoord(ggbangarg1))[0] == '=' && string((xcoord(ggbangarg1))[1]) == string(X),"
+ "normal(regroup(angle(point(0,0,0),"
+ "point( ggbangarg0[2][2][2][0] , ggbangarg0[2][2][2][1] , ggbangarg0[2][2][2][2]),"
+ "point( ggbangarg1[2][2][2][0] , ggbangarg1[2][2][2][1] , ggbangarg1[2][2][2][2] ) ))),"
// case 3D line def with command and plane with linear
// equation
+ " when ( xcoord(ggbangarg0) == string(X) && type(xcoord(ggbangarg1)) == DOM_INT,"
+ "normal(regroup(angle(point(0,0,0),"
+ "point( coeff(expr(ggbangarg0)[0][2],\u03BB,1) , coeff(expr(ggbangarg0)[1][2],\u03BB,1) , coeff(expr(ggbangarg0)[2][2],\u03BB,1) ),"
+ "point(xcoord(ggbangarg1),ycoord(ggbangarg1),zcoord(ggbangarg1)) ))) , "
// case 3D line from inputBar and plane with linear
// equation
+ "when ( (xcoord(ggbangarg0))[0] == '=' && string((xcoord(ggbangarg0))[1]) == string(X) && type(xcoord(ggbangarg1)) == DOM_INT ,"
+ "normal(regroup(angle(point(0,0,0),"
+ "point( ggbangarg0[2][2][2][0] , ggbangarg0[2][2][2][1] , ggbangarg0[2][2][2][2]),"
+ "point(xcoord(ggbangarg1),ycoord(ggbangarg1),zcoord(ggbangarg1)) ))) , "
+ " ? ) ) ) ) ) ) ) ) ) ) ) ) ][1]");
p("Angle.3", "[[[ggbangarg0:=%0], [ggbangarg1:=%1], [ggbangarg2:=%2]], "
// syntax Angle[Point, Apex, Point]
+ "when ( (ggbangarg0)[0] == 'pnt' && (ggbangarg1)[0] == 'pnt' && (ggbangarg2)[0] == 'pnt' ,"
+ "normal(regroup(angle(point(xcoord(ggbangarg1),ycoord(ggbangarg1),zcoord(ggbangarg1)),point(xcoord(ggbangarg0),ycoord(ggbangarg0),zcoord(ggbangarg0)),point(xcoord(ggbangarg2),ycoord(ggbangarg2),zcoord(ggbangarg2))))), "
// syntax Angle[Point, Apex, Angle]
// third parameter is angle given in degree
+ "when ( (ggbangarg0)[0] == 'pnt' && (ggbangarg1)[0] == 'pnt' && "
+ "type(evalf(ggbangarg2)) == DOM_FLOAT , "
+ "normal(regroup(rotation(ggbangarg1,ggbangarg2,ggbangarg0))) , "
+ "? ) )][1]");
// p("Angle.3", "normal(regroup(angle(%1,%0,%2)))");
// eg distance((4,5),(0,3))
// eg distance((2,3,4),(0,3,1))
// eg distance(conic(y=x^2),(0,3))
// don't want normal(), eg Distance[(a,b),(c,d)]
// bit do want it for Distance[(0.5,0.5),x^2+y^2=1]
// use type(evalf(ggbarg1))==DOM_FLOAT to catch DOM_INT, DOM_FLOAT,
// DOM_RAT, DOM_IDENT (eg pi)
p("Distance.2",
"[[[ggbdisans:=0/0],[ggbdisarg0:=%0],[ggbdisarg1:=%1],[ggbdisans:=when(ggbdisarg0[0]!='pnt',undef,when(type(evalf(ggbdisarg1))==DOM_FLOAT,undef,regroup(distance(ggbdisarg0,"
+
// #3907 add "y=" for functions but not points
"when(ggbdisarg1[0]!='pnt' && ggbdisarg1[0] != '=',y=ggbdisarg1,"
+
// if variable list contains 'z', wrap in plane()
"when(count_eq(z,lname(ggbdisarg1))==0,ggbdisarg1,plane(ggbdisarg1))"
+ ")" + "))))]],"
+ "when(lname(ggbdisans)=={},normal(ggbdisans),ggbdisans)][1]");
// regroup: y = -2 a + b + 2x -> y = 2x - 2 a + b
// don't want normal(), eg Line[(a,b),(c,d)]
// X=point(xcoord(ggblinearg0+\u03BB*(ggblinearg1-ggblinearg0)),ycoord(ggblinearg0+\u03BB*(ggblinearg1-ggblinearg0)),zcoord(ggblinearg0+\u03BB*(ggblinearg1-ggblinearg0)))
String line2def = "[[ggblinearg0:=%0],[ggblinearg1:=%1],"
+ "when(is_3dpoint(ggblinearg0),"
+ "when(ggblinearg1[0]=='pnt',"
// case Line[3dPoint,3dPoint]
+ "regroup(equation(cat(\"X=\",ggblinearg0,\"+\u03BB*\",point(xcoord(ggblinearg1-ggblinearg0),ycoord(ggblinearg1-ggblinearg0),zcoord(ggblinearg1-ggblinearg0))))),"
// case Line[3dPoint,Vect]
+ "equation(cat(\"X=\",ggblinearg0,\"+\u03BB*\",point(ggblinearg1[0],ggblinearg1[1],when(size(ggblinearg1) == 3,ggblinearg1[2],0))))),"
// case Line[2dPoint,2dPoint] or Line[2dPoint,Vector]
+ "regroup(equation(line(ggblinearg0,ggblinearg1))))][2]";
p("Line.2", line2def);
// TODO: return Segment() not equation
p("Segment.2", line2def);
p("Point.1",
"when(length(%0)==3,point(xcoord(%0),ycoord(%0),zcoord(%0)),point(xcoord(%0),ycoord(%0)))");
p("Point.2",
"when(length(%0)==3,{point(xcoord(%0),ycoord(%0),zcoord(%0)),point(xcoord(%1),ycoord(%1),zcoord(%1))},{point(xcoord(%0),ycoord(%0)),point(xcoord(%1),ycoord(%1))})");
// p("Midpoint.2",
// "[[ggbans:=factor((normal(convert(coordinates(midpoint(%0,%1)),25))))],"
// +
// "(ggbans[0],ggbans[1])][1]");
// normal: nice form for Midpoint[(1/2,pi),(1,1)]
// factor: nice form for Midpoint[(a,b),(c,d)]
p("Midpoint.2",
"convert(factor((normal(coordinates(midpoint(%0,%1))))),25)");
p("OrthogonalLine.2", "equation(perpendicular(%0,line(%1)))");
// TODO: needs to get back from Giac into GeoGebra as a parametric eqn
// p("Curve.5", "equation(plotparam([%0,%1],%2,%3,%4))");
// p("Polygon.N", "polygon(%)");
// p("PolyLine.N", "open_polygon(%)");
p("Tangent.2",
"[[[ggbtanarg0:=%0],[ggbtanarg1:=%1],[ggbtanvar:=when(size(lname(ggbtanarg1) intersect [x]) == 0,lname(ggbtanarg1)[0],x)]],"
+ "when((%0)[0]=='pnt'," + "when((ggbtanarg1)[0]=='=',"
+
// Tangent[conic/implicit, point on curve]
"when ( type(equation(tangent(ggbtanarg1,ggbtanarg0))) == DOM_LIST,"
+ "equation(tangent(ggbtanarg1,ggbtanarg0)),"
// needed for TRAC-2635
// convert to list the result
+ "{equation(tangent(ggbtanarg1,ggbtanarg0))} )," +
// Tangent[point, function]
// just use x-coordinate real(%0[1])
"y=normal(subst(diff(ggbtanarg1,ggbtanvar),ggbtanvar=real(ggbtanarg0[1]))*(x-real(ggbtanarg0[1]))+subst(ggbtanarg1,ggbtanvar=real(%0[1])))) "
+ "," +
// Tangent[x-value, function]
// use lname(function) instead of x
// e.g. lname(sin(t)) = t
// needed for #5526
"y=normal(subst(diff(ggbtanarg1,ggbtanvar),ggbtanvar=ggbtanarg0)*(x-(ggbtanarg0))+subst(ggbtanarg1,ggbtanvar=ggbtanarg0))"
+ ")][1]");
// p("TangentThroughPoint.2",
// "[[ggbans:=?],[ggbans:=equation(tangent(when((%1)[0]=='=',%1,y=%1),%0))],"
// +
// "[ggbans:=when(((ggbans)[0])=='=' && lhs(ggbans)==1 &&
// rhs(ggbans)==0,?,ggbans)],"
// +
// "[ggbans:=when(type(ggbans)==DOM_LIST,ggbans,{ggbans})],ggbans][4]");
// see ToPoint.1
// eg Dot[Vector[(a,b)],Vector[(c,d)]]
p("Vector.1",
// "point(convert(coordinates(%0),25))");
"when(is_3dpoint(%0)," +
// 3D
// "ggbvect[((%0)[1])[0], ((%0)[1])[1], ((%0)[1])[2]]"+
"ggbvect[xcoord(%0),ycoord(%0),zcoord(%0)]" + ","
+ "when((%0)[0]=='pnt'," +
// 2D point
// "ggbvect[real((%0)[1]), im((%0)[1])]"+
"ggbvect[xcoord(%0),ycoord(%0)]" + ","
+ "when(im(%0)==ggbvect[0,0]," +
// already a vector
"%0" + "," +
// complex
"ggbvect[re(%0),im(%0)]" + ")))");
p("Vector.2", "when(is_3dpoint(%0)||is_3dpoint(%1)," +
// 3D points
// "ggbvect[((%1)[1])[0]-((%0)[1])[0], ((%1)[1])[1]-((%0)[1])[1],
// ((%1)[1])[2]-((%0)[1])[2] ]"+
"ggbvect[xcoord(%1)-xcoord(%0),ycoord(%1)-ycoord(%0),zcoord(%1)-zcoord(%0)]"
+ "," + "when((%0)[0]=='pnt'," +
// 2D points
// "ggbvect[real((%1)[1])-real((%0)[1]),
// im((%1)[1])-im((%0)[1])]"+
"ggbvect[xcoord(%1)-xcoord(%0),ycoord(%1)-ycoord(%0)]" + "," +
// numbers
"ggbvect[%0,%1]" + "))");
p("OrthogonalVector.1",
"when(is_3dpoint(%0),?,"
+ "when((%0)[0]=='=',convert(when(count_eq(z,lname(%0))==0,[xcoord(%0),ycoord(%0)],[xcoord(%0),ycoord(%0),zcoord(%0)]),25),"
+ "convert([[0,-1],[1,0]]*(%0),25)))");
p("UnitOrthogonalVector.1",
"when(type(%0)==DOM_LIST && size(%0) != 2,?,"
+ "when(is_3dpoint(%0),?,"
// vector given as point or list
+ "when( subtype(%0) == 27 || (%0)[0] == 'pnt' || type(%0) == DOM_LIST,"
// case UnitOrthogonalVector[Vector]
+ "regroup(convert(unitV([-ycoord(%0),xcoord(%0)]),25)) , "
// case UnitOrthogonalVecto[Line]
// UnitOrthogonalVector[Segment]
+ "[[gguv:=unitV(when(count_eq(z,lname(%0))==0,[xcoord(%0),ycoord(%0)],[xcoord(%0),ycoord(%0),zcoord(%0)]))],when ((gguv)[0] == 'undef',"
+ "point(?,?),"
+ "when (size(gguv) == 1 , "
+ "regroup(convert("
+ "point(getNum(gguv)[0]/getDenom(gguv),"
+ "getNum(gguv)[1]/getDenom(gguv) ),25)) , "
+ "regroup(convert(gguv,25)) ) )][1]"
+ " ) ) )");
p("UnitVector.1",
"[[ggin:=%0],[ggbuvans:=when(type(ggin)==DOM_LIST,normalize(ggin),when((ggin)[0]=='=',"
+ "convert([unitV(coeff(left(ggin)-right(ggin),y,1),-coeff(left(ggin)-right(ggin),x,1))],25),"
+ "when(ggin[0]='pnt' && size(ggin[1])==3,normal(unitV(ggin)),convert(unitV([real(ggin[1]),im(ggin[1])]),25))))],ggbuvans][2]");
// Tecna[(10,1),log10(x)]
return commandMap;
}
}