From b4d006897f65e2d5309d9b4d3bb3f2a5ed4d7d24 Mon Sep 17 00:00:00 2001 From: cmwslw Date: Wed, 21 Nov 2018 00:09:34 -0800 Subject: [PATCH 1/8] Improve stringification. --- expreduce/atoms/ex_complex.go | 28 +++++------- expreduce/atoms/ex_symbol.go | 3 ++ expreduce/builtin_arithmetic.go | 81 +++++++++++++++++++++++++++++++-- expreduce/string.go | 14 +++++- 4 files changed, 105 insertions(+), 21 deletions(-) diff --git a/expreduce/atoms/ex_complex.go b/expreduce/atoms/ex_complex.go index 3b3ff3a..37d26ae 100644 --- a/expreduce/atoms/ex_complex.go +++ b/expreduce/atoms/ex_complex.go @@ -14,28 +14,24 @@ type Complex struct { needsEval bool } -func (cmplx *Complex) StringForm(p expreduceapi.ToStringParams) string { - if p.Form == "FullForm" { - return fmt.Sprintf("Complex[%v, %v]", cmplx.Re, cmplx.Im) - } - iString := "I" - if p.Form == "TeXForm" { - iString = "i" - } +func (cmplx *Complex) AsExpr() expreduceapi.Ex { + iSym := S("I") reInt, reIsInt := cmplx.Re.(*Integer) imInt, imIsInt := cmplx.Im.(*Integer) if reIsInt && reInt.Val.Sign() == 0 { if imIsInt && imInt.Val.Int64() == 1 { - return iString - } - if imIsInt && imInt.Val.Int64() == -1 { - return fmt.Sprintf("(-%v)", iString) + return iSym } - p.PreviousHead = "System`Times" - return fmt.Sprintf("(%v*%v)", cmplx.Im.StringForm(p), iString) + return E(S("Times"), cmplx.Im, iSym) + } + return E(S("Plus"), cmplx.Re, E(S("Times"), cmplx.Im, iSym)) +} + +func (cmplx *Complex) StringForm(p expreduceapi.ToStringParams) string { + if p.Form == "FullForm" { + return fmt.Sprintf("Complex[%v, %v]", cmplx.Re, cmplx.Im) } - p.PreviousHead = "System`Plus" - return fmt.Sprintf("(%v + %v*%v)", cmplx.Re.StringForm(p), cmplx.Im.StringForm(p), iString) + return cmplx.AsExpr().StringForm(p) } func (cmplx *Complex) IsEqual(other expreduceapi.Ex) string { diff --git a/expreduce/atoms/ex_symbol.go b/expreduce/atoms/ex_symbol.go index fea50d4..36775b2 100644 --- a/expreduce/atoms/ex_symbol.go +++ b/expreduce/atoms/ex_symbol.go @@ -21,6 +21,9 @@ func formatSymName(name string, params expreduceapi.ToStringParams) string { if name == "E" { return "e" } + if name == "I" { + return "i" + } if name == "Pi" { return "\\pi" } diff --git a/expreduce/builtin_arithmetic.go b/expreduce/builtin_arithmetic.go index 3394398..c64f420 100644 --- a/expreduce/builtin_arithmetic.go +++ b/expreduce/builtin_arithmetic.go @@ -1,6 +1,7 @@ package expreduce import ( + "fmt" "math/big" "strings" @@ -113,6 +114,30 @@ func collectTerms(e expreduceapi.ExpressionInterface) expreduceapi.ExpressionInt return collected } +func splitFrac(ex expreduceapi.Ex) (num expreduceapi.Ex, den expreduceapi.Ex) { + asPow, isPow := atoms.HeadAssertion(ex, "System`Power") + if isPow { + if asPow.Len() != 2 { + return ex, nil + } + powInt, powIsInt := asPow.GetPart(2).(*atoms.Integer) + if !powIsInt { + return ex, nil + } + if powInt.Val.Int64() == -1 { + return nil, asPow.GetPart(1) + } + } + asRat, isRat := ex.(*atoms.Rational) + if isRat { + if asRat.Num.Int64() == 1 { + return nil, atoms.NewInteger(asRat.Den) + } + return atoms.NewInteger(asRat.Num), atoms.NewInteger(asRat.Den) + } + return ex, nil +} + func getArithmeticDefinitions() (defs []Definition) { defs = append(defs, Definition{ Name: "Plus", @@ -174,11 +199,59 @@ func getArithmeticDefinitions() (defs []Definition) { if params.Form == "TeXForm" { delim = " " } - ok, res := toStringInfix(this.GetParts()[1:], delim, "System`Times", params) - if ok && strings.HasPrefix(res, "(-1)"+delim) { - return ok, "-" + res[5:] + + timesParts := atoms.E(atoms.S("Times")) + for _, part := range this.GetParts()[1:] { + partAsComplex, partIsComplex := part.(*atoms.Complex) + if partIsComplex { + asExpr := partAsComplex.AsExpr() + cmplxTimes, cmplxIsTimes := atoms.HeadAssertion(asExpr, "System`Times") + if cmplxIsTimes { + for _, cmplxPart := range cmplxTimes.GetParts()[1:] { + timesParts.AppendEx(cmplxPart) + } + continue + } + } + timesParts.AppendEx(part) + } + + num := atoms.E(atoms.S("Times")) + den := atoms.E(atoms.S("Times")) + for _, part := range timesParts.GetParts()[1:] { + numPart, denPart := splitFrac(part) + if numPart != nil { + num.AppendEx(numPart) + } + if denPart != nil { + den.AppendEx(denPart) + } + } + if den.Len() > 0 { + numOk, numStr := toStringInfix(num.GetParts()[1:], delim, "System`Times", params) + if num.Len() == 1 { + numOk, numStr = true, num.GetPart(1).StringForm(params) + } + denOk, denStr := toStringInfix(den.GetParts()[1:], delim, "System`Times", params) + if den.Len() == 1 { + denOk, denStr = true, den.GetPart(1).StringForm(params) + } + if !numOk || !denOk { + return false, "" + } + if params.Form == "TeXForm" { + return true, fmt.Sprintf("\\frac{%v}{%v}", numStr, denStr) + } + return true, fmt.Sprintf("(%v)/(%v)", numStr, denStr) + } + ok, res := toStringInfix(num.GetParts()[1:], delim, "System`Times", params) + if !ok { + return false, "" + } + if strings.HasPrefix(res, "(-1)"+delim) { + return true, "-" + res[5:] } - return ok, res + return true, res }, legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex { // Calls without argument receive identity values diff --git a/expreduce/string.go b/expreduce/string.go index 59dbcf9..f6709f1 100644 --- a/expreduce/string.go +++ b/expreduce/string.go @@ -75,8 +75,17 @@ func toStringInfixAdvanced(parts []expreduceapi.Ex, delim string, thisHead strin buffer.WriteString(start) } nextParams := params - nextParams.PreviousHead = thisHead for i := 0; i < len(parts); i++ { + useTeXGrouping := false + if thisHead == "System`Power" && params.Form == "TeXForm" && i == 1 { + nextParams.PreviousHead = "" + useTeXGrouping = true + } else { + nextParams.PreviousHead = thisHead + } + if useTeXGrouping { + buffer.WriteString("{") + } if surroundEachArg { buffer.WriteString("(") buffer.WriteString(parts[i].StringForm(nextParams)) @@ -84,6 +93,9 @@ func toStringInfixAdvanced(parts []expreduceapi.Ex, delim string, thisHead strin } else { buffer.WriteString(parts[i].StringForm(nextParams)) } + if useTeXGrouping { + buffer.WriteString("}") + } if i != len(parts)-1 { buffer.WriteString(delim) } From da73d3a23f387f84c5477c5e3f077bb5c5142264 Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 18:51:26 -0800 Subject: [PATCH 2/8] Lazy loading of Rubi rules. --- expreduce.go | 6 +++--- expreduce/atoms/ex_complex.go | 3 +++ expreduce/resources.go | 4 ++-- expreduce/resources/calculus.m | 4 ++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/expreduce.go b/expreduce.go index d42ae33..b7a0606 100644 --- a/expreduce.go +++ b/expreduce.go @@ -24,7 +24,7 @@ var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") var netprofile = flag.Bool("netprofile", false, "Enable live profiling at http://localhost:8080/debug/pprof/") var scriptfile = flag.String("script", "", "script `file` to read from") var initfile = flag.String("initfile", "", "A script to run on initialization.") -var loadRubi = flag.Bool("loadrubi", true, "Load the Rubi definitions for integral support on startup.") +var preloadRubi = flag.Bool("preloadrubi", false, "Preload the Rubi definitions for integral support on startup.") func main() { flag.Parse() @@ -44,8 +44,8 @@ func main() { fmt.Printf("Welcome to Expreduce!\n\n") es := expreduce.NewEvalState() - if *loadRubi { - fmt.Println("Loading Rubi snapshot for integral support. Disable with -loadrubi=false.") + if *preloadRubi { + fmt.Println("Pre-loading Rubi snapshot for integral support. Disable with -preloadrubi=false.") es.Eval(atoms.E(atoms.S("LoadRubiBundledSnapshot"))) fmt.Println("Done loading Rubi snapshot.") fmt.Print("\n") diff --git a/expreduce/atoms/ex_complex.go b/expreduce/atoms/ex_complex.go index 37d26ae..ef66507 100644 --- a/expreduce/atoms/ex_complex.go +++ b/expreduce/atoms/ex_complex.go @@ -24,6 +24,9 @@ func (cmplx *Complex) AsExpr() expreduceapi.Ex { } return E(S("Times"), cmplx.Im, iSym) } + if imIsInt && imInt.Val.Int64() == 1 { + return E(S("Plus"), cmplx.Re, iSym) + } return E(S("Plus"), cmplx.Re, E(S("Times"), cmplx.Im, iSym)) } diff --git a/expreduce/resources.go b/expreduce/resources.go index b08cd39..d4f4c02 100644 --- a/expreduce/resources.go +++ b/expreduce/resources.go @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3916d384fed3f084e23c0984d17c4cc22547dc7a10b4ca6f70a3866fcf5beca7 -size 1339970 +oid sha256:de8042936af3daea88a4f4af8ffb88dc239b1f617d391ee29ddb3ec8c6c3cbef +size 1340326 diff --git a/expreduce/resources/calculus.m b/expreduce/resources/calculus.m index 696e6ef..ba82efc 100644 --- a/expreduce/resources/calculus.m +++ b/expreduce/resources/calculus.m @@ -67,6 +67,10 @@ Integrate[a_,{x_Symbol,start_,end_}] := (ReplaceAll[Integrate[a, x],x->end] - ReplaceAll[Integrate[a, x],x->start]) // Simplify; Integrate[a_,x_Symbol] := Module[{cleanedA, replaceRules}, + If[!MemberQ[$ContextPath, "Rubi`"], + Print["Loading Rubi rules for integration. This happens once. Preload on startup with -preloadrubi."]; + LoadRubiBundledSnapshot[] + ]; replaceRules = genSubscriptReplacements[a]; cleanedA = a /. replaceRules[[1]]; (Rubi`Int[cleanedA, x] /. replaceRules[[2]]) // Simplify From a9c7f199f8edfbb91ce860dfc39638a76e27fee9 Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 19:41:02 -0800 Subject: [PATCH 3/8] Improve stringification of negatives. --- expreduce/atoms/ex_integer.go | 9 ----- expreduce/builtin_arithmetic.go | 57 ++++++++++++++++++++++++++++---- expreduce/resources.go | 4 +-- expreduce/resources/arithmetic.m | 3 ++ 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/expreduce/atoms/ex_integer.go b/expreduce/atoms/ex_integer.go index dcf0323..dbf0196 100644 --- a/expreduce/atoms/ex_integer.go +++ b/expreduce/atoms/ex_integer.go @@ -5,7 +5,6 @@ import ( "hash/fnv" "math/big" - "github.com/corywalker/expreduce/expreduce/parser/parens" "github.com/corywalker/expreduce/pkg/expreduceapi" ) @@ -20,14 +19,6 @@ type Integer struct { }*/ func (thisInt *Integer) StringForm(params expreduceapi.ToStringParams) string { - if thisInt.Val.Cmp(big.NewInt(0)) < 0 { - if parens.NeedsParens("System`Times", params.PreviousHead) { - if params.Form == "TeXForm" { - return fmt.Sprintf("{(%d)}", thisInt.Val) - } - return fmt.Sprintf("(%d)", thisInt.Val) - } - } return fmt.Sprintf("%d", thisInt.Val) } diff --git a/expreduce/builtin_arithmetic.go b/expreduce/builtin_arithmetic.go index c64f420..493ee80 100644 --- a/expreduce/builtin_arithmetic.go +++ b/expreduce/builtin_arithmetic.go @@ -1,12 +1,14 @@ package expreduce import ( + "bytes" "fmt" "math/big" "strings" "github.com/corywalker/expreduce/expreduce/atoms" "github.com/corywalker/expreduce/expreduce/iterspec" + "github.com/corywalker/expreduce/expreduce/parser/parens" "github.com/corywalker/expreduce/pkg/expreduceapi" ) @@ -142,8 +144,46 @@ func getArithmeticDefinitions() (defs []Definition) { defs = append(defs, Definition{ Name: "Plus", Default: "0", - toString: func(this expreduceapi.ExpressionInterface, params expreduceapi.ToStringParams) (bool, string) { - return toStringInfix(this.GetParts()[1:], " + ", "System`Plus", params) + toString: func(this expreduceapi.ExpressionInterface, p expreduceapi.ToStringParams) (bool, string) { + thisHead := "System`Plus" + parts := this.GetParts()[1:] + if p.Form != "InputForm" && p.Form != "OutputForm" && p.Form != "TeXForm" { + return false, "" + } + if len(parts) < 2 { + return false, "" + } + addParens := parens.NeedsParens(thisHead, p.PreviousHead) + var buffer bytes.Buffer + if addParens { + if p.Form == "TeXForm" { + buffer.WriteString("{\\left(") + } else { + buffer.WriteString("(") + } + } + nextParams := p + nextParams.PreviousHead = thisHead + for i := 0; i < len(parts); i++ { + toWrite := parts[i].StringForm(nextParams) + if i != 0 { + if toWrite[0] == '-' { + buffer.WriteString(" - ") + toWrite = toWrite[1:] + } else { + buffer.WriteString(" + ") + } + } + buffer.WriteString(toWrite) + } + if addParens { + if p.Form == "TeXForm" { + buffer.WriteString("\\right)}") + } else { + buffer.WriteString(")") + } + } + return true, buffer.String() }, legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex { // Calls without argument receive identity values @@ -239,17 +279,22 @@ func getArithmeticDefinitions() (defs []Definition) { if !numOk || !denOk { return false, "" } + prefix := "" + if strings.HasPrefix(numStr, "-1"+delim) { + prefix = "-" + numStr = numStr[3:] + } if params.Form == "TeXForm" { - return true, fmt.Sprintf("\\frac{%v}{%v}", numStr, denStr) + return true, fmt.Sprintf("%v\\frac{%v}{%v}", prefix, numStr, denStr) } - return true, fmt.Sprintf("(%v)/(%v)", numStr, denStr) + return true, fmt.Sprintf("%v(%v)/(%v)", prefix, numStr, denStr) } ok, res := toStringInfix(num.GetParts()[1:], delim, "System`Times", params) if !ok { return false, "" } - if strings.HasPrefix(res, "(-1)"+delim) { - return true, "-" + res[5:] + if strings.HasPrefix(res, "-1"+delim) { + return true, "-" + res[3:] } return true, res }, diff --git a/expreduce/resources.go b/expreduce/resources.go index d4f4c02..5f38d06 100644 --- a/expreduce/resources.go +++ b/expreduce/resources.go @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de8042936af3daea88a4f4af8ffb88dc239b1f617d391ee29ddb3ec8c6c3cbef -size 1340326 +oid sha256:c49043712e79f86317a58233aa619034ef3f1074c1e199339acd301d72b07957 +size 1340442 diff --git a/expreduce/resources/arithmetic.m b/expreduce/resources/arithmetic.m index f5f68ed..390c75f 100644 --- a/expreduce/resources/arithmetic.m +++ b/expreduce/resources/arithmetic.m @@ -213,6 +213,9 @@ ESameTest[I/(2 Sqrt[3] a^2), (0+1/6*I)*3^(1/2)*a^(-2)], (* Test wouldntBeLessThanNegOne. *) ESameTest[(1/3)*3^(-1/2), (1/3)*3^(-1/2)], + + ESameTest[Sqrt[2/\[Pi]], Sqrt[2]*Sqrt[1/Pi]], + ESameTest[Sqrt[3/(2 \[Pi])], Sqrt[3/2]*Sqrt[1/Pi]], ], EKnownFailures[ ESameTest[-2^(1/3), (-2)*2^(-2/3)], ESameTest[-2^(1+a), (-2)*2^(a)], From 68e5298e8ad3291072f07bab8c8d238232f541ee Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 20:54:00 -0800 Subject: [PATCH 4/8] RotationMatrix --- expreduce/builtin_trig.go | 2 ++ expreduce/parser/interp.go | 1 + expreduce/resources.go | 4 ++-- expreduce/resources/matrix.m | 1 + expreduce/resources/trig.m | 20 ++++++++++++++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/expreduce/builtin_trig.go b/expreduce/builtin_trig.go index 56ea3a5..57d2c09 100644 --- a/expreduce/builtin_trig.go +++ b/expreduce/builtin_trig.go @@ -63,5 +63,7 @@ func getTrigDefinitions() (defs []Definition) { Name: "TrigToExp", OmitDocumentation: true, }) + defs = append(defs, Definition{Name: "Degree"}) + defs = append(defs, Definition{Name: "RotationMatrix"}) return } diff --git a/expreduce/parser/interp.go b/expreduce/parser/interp.go index 57c0650..a7d93a0 100644 --- a/expreduce/parser/interp.go +++ b/expreduce/parser/interp.go @@ -480,6 +480,7 @@ func ReplaceSyms(in string) string { in = strings.Replace(in, "\\[Omega]", "ω", -1) in = strings.Replace(in, "\\[CapitalOmega]", "Ω", -1) in = strings.Replace(in, "\\[Alpha]", "α", -1) + in = strings.Replace(in, "\\[Theta]", "θ", -1) return in } diff --git a/expreduce/resources.go b/expreduce/resources.go index 5f38d06..bfbc219 100644 --- a/expreduce/resources.go +++ b/expreduce/resources.go @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c49043712e79f86317a58233aa619034ef3f1074c1e199339acd301d72b07957 -size 1340442 +oid sha256:9a782214470c52221d715feed9a954f418a3c12732d161a0cd3063990125efc9 +size 1341938 diff --git a/expreduce/resources/matrix.m b/expreduce/resources/matrix.m index 7e9ae56..8a76d30 100644 --- a/expreduce/resources/matrix.m +++ b/expreduce/resources/matrix.m @@ -74,6 +74,7 @@ }; Dot::usage = "`a.b` computes the product of `a` and `b` for vectors and matrices."; +Dot[m_?MatrixQ,v_?VectorQ]:=Table[m[[idx]].v,{idx,Length[v]}]; Attributes[Dot] = {Flat, OneIdentity, Protected}; Tests`Dot = { ESimpleExamples[ diff --git a/expreduce/resources/trig.m b/expreduce/resources/trig.m index ec8955a..93fa0fc 100644 --- a/expreduce/resources/trig.m +++ b/expreduce/resources/trig.m @@ -116,3 +116,23 @@ ESameTest[(I (E^(-I x)-E^(I x)))/(E^(-I x)+E^(I x)), TrigToExp[Tan[x]]], ] }; + +Degree::usage = "`Degree` stands for Pi/180." +Degree = Pi/180; +Attributes[Degree] = {Constant,Protected,ReadProtected}; +Tests`Degree = { + ESimpleExamples[ + ESameTest[1, Sin[90 Degree]], + ] +}; + +RotationMatrix::usage = "`RotationMatrix[θ]` yields a rotation matrix for the angle `θ`."; +RotationMatrix[θ_] := {{Cos[θ],-Sin[θ]},{Sin[θ],Cos[θ]}}; +RotationMatrix[θ_, {x_, 0, 0}] := {{(x^3 Conjugate[x]^3)/Abs[x]^6,0,0},{0,Cos[\[Theta]],-((x^2 Conjugate[x] Sin[\[Theta]])/Abs[x]^3)},{0,(x Conjugate[x]^2 Sin[\[Theta]])/Abs[x]^3,(x^3 Conjugate[x]^3 Cos[\[Theta]])/Abs[x]^6}}; +RotationMatrix[θ_, {0, y_, 0}] := {{Cos[\[Theta]],0,(y^2 Conjugate[y] Sin[\[Theta]])/Abs[y]^3},{0,(y^3 Conjugate[y]^3)/Abs[y]^6,0},{-((y Conjugate[y]^2 Sin[\[Theta]])/Abs[y]^3),0,(y^3 Conjugate[y]^3 Cos[\[Theta]])/Abs[y]^6}}; +RotationMatrix[θ_, {0, 0, z_}] := {{Cos[\[Theta]],-((z Sin[\[Theta]])/Abs[z]),0},{(Conjugate[z] Sin[\[Theta]])/Abs[z],(z Conjugate[z] Cos[\[Theta]])/Abs[z]^2,0},{0,0,(z Conjugate[z])/Abs[z]^2}}; +Tests`RotationMatrix = { + ESimpleExamples[ + ESameTest[{{0, -1}, {1, 0}}, RotationMatrix[90 Degree]], + ] +}; From 2e6afc5a7ff4303919850dc0cbd3bdd219bc0f12 Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 20:56:05 -0800 Subject: [PATCH 5/8] Fix some tests. --- expreduce/resources.go | 4 ++-- expreduce/resources/arithmetic.m | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/expreduce/resources.go b/expreduce/resources.go index bfbc219..7a5f7d5 100644 --- a/expreduce/resources.go +++ b/expreduce/resources.go @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a782214470c52221d715feed9a954f418a3c12732d161a0cd3063990125efc9 -size 1341938 +oid sha256:ca75da5330e0ff868f5c798586fe495f55373bd61b4e33d9589fdb06ba6039e7 +size 1341942 diff --git a/expreduce/resources/arithmetic.m b/expreduce/resources/arithmetic.m index 390c75f..006ba88 100644 --- a/expreduce/resources/arithmetic.m +++ b/expreduce/resources/arithmetic.m @@ -21,10 +21,10 @@ EStringTest["(1.*(a + b))", "(a + b)/1."], EStringTest["(2*(a + b))", "2*(a + b)"], EStringTest["(a*(b + c))", "a*(b + c)"], - EStringTest["(-a + -b)", "-1*(a + b)"], - EStringTest["(-a + -b)", "-(a + b)"], + EStringTest["(-a - b)", "-1*(a + b)"], + EStringTest["(-a - b)", "-(a + b)"], EStringTest["((-1.)*(a + b))", "-1.*(a + b)"], - EStringTest["(-a + -b)", "(a + b)/-1"], + EStringTest["(-a - b)", "(a + b)/-1"], EStringTest["((-1.)*(a + b))", "(a + b)/-1."], (*Test that we do not delete all the addends*) From 6ad4b293575d90528e917384f58fb65ff3b92d2d Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 21:38:42 -0800 Subject: [PATCH 6/8] Grad function. --- expreduce/builtin_calculus.go | 1 + expreduce/builtin_list.go | 25 ++++++++++++++++++++++++- expreduce/evalstate.go | 1 + expreduce/resources.go | 4 ++-- expreduce/resources/calculus.m | 13 ++++++++++++- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/expreduce/builtin_calculus.go b/expreduce/builtin_calculus.go index 3cb2263..51c260f 100644 --- a/expreduce/builtin_calculus.go +++ b/expreduce/builtin_calculus.go @@ -2,6 +2,7 @@ package expreduce func getCalculusDefinitions() (defs []Definition) { defs = append(defs, Definition{Name: "D"}) + defs = append(defs, Definition{Name: "Grad"}) defs = append(defs, Definition{Name: "Integrate"}) return } diff --git a/expreduce/builtin_list.go b/expreduce/builtin_list.go index 90a0b5c..ad4901f 100644 --- a/expreduce/builtin_list.go +++ b/expreduce/builtin_list.go @@ -43,6 +43,28 @@ func toStringList(this expreduceapi.ExpressionInterface, params expreduceapi.ToS return true, buffer.String() } +func toStringPart(this expreduceapi.ExpressionInterface, params expreduceapi.ToStringParams) (bool, string) { + if params.Form == "FullForm" { + return false, "" + } + subParams := params + subParams.PreviousHead = "" + var buffer bytes.Buffer + for i, e := range this.GetParts()[1:] { + if i == 0 { + buffer.WriteString(e.StringForm(params)) + buffer.WriteString("[[") + } else { + buffer.WriteString(e.StringForm(subParams)) + if i != len(this.GetParts()[1:])-1 { + buffer.WriteString(",") + } + } + } + buffer.WriteString("]]") + return true, buffer.String() +} + func memberQ(components []expreduceapi.Ex, item expreduceapi.Ex, es expreduceapi.EvalStateInterface) bool { for _, part := range components { if matchq, _ := matcher.IsMatchQ(part, item, matcher.EmptyPD(), es); matchq { @@ -496,7 +518,8 @@ func getListDefinitions() (defs []Definition) { }, }) defs = append(defs, Definition{ - Name: "Part", + Name: "Part", + toString: toStringPart, legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex { if len(this.GetParts()) == 1 { return this diff --git a/expreduce/evalstate.go b/expreduce/evalstate.go index 74d8455..e64b7d9 100644 --- a/expreduce/evalstate.go +++ b/expreduce/evalstate.go @@ -183,6 +183,7 @@ func (es *EvalState) Init(loadAllDefs bool) { es.MarkSeen("System`EllipticF") es.MarkSeen("System`ProductLog") es.MarkSeen("System`FresnelS") + es.MarkSeen("System`Gamma") es.MarkSeen("System`Cosh") es.MarkSeen("System`Sinh") diff --git a/expreduce/resources.go b/expreduce/resources.go index 7a5f7d5..f7b1dda 100644 --- a/expreduce/resources.go +++ b/expreduce/resources.go @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca75da5330e0ff868f5c798586fe495f55373bd61b4e33d9589fdb06ba6039e7 -size 1341942 +oid sha256:42b3910e4654d0755c195643af1eafef9312800c9ddd5ad75b0bfe74905b8c9f +size 1342570 diff --git a/expreduce/resources/calculus.m b/expreduce/resources/calculus.m index ba82efc..3bb5c8e 100644 --- a/expreduce/resources/calculus.m +++ b/expreduce/resources/calculus.m @@ -14,6 +14,7 @@ D[Sin[a_], x_] := D[a,x] Cos[a]; D[Cos[a_], x_] := -D[a,x] Sin[a]; D[Exp[x_Symbol], x_Symbol] := Exp[x]; +D[l_List, x_] := Table[D[l[[idx]], x], {idx, Length[l]}]; Attributes[D] = {ReadProtected, Protected}; Tests`D = { ESimpleExamples[ @@ -39,7 +40,17 @@ ESameTest[-Cos[Cos[x]] Sin[x], D[Sin[Cos[x]],x]], ESameTest[Cos[Log[x]]/x, D[Sin[Log[x]],x]], ESameTest[-(Sin[Log[x]]/x), D[Cos[Log[x]],x]], - ESameTest[1-(1+Cot[x]) Sin[x+Log[Sin[x]]], D[Cos[Log[Sin[x]]+x]+x,x]] + ESameTest[1-(1+Cot[x]) Sin[x+Log[Sin[x]]], D[Cos[Log[Sin[x]]+x]+x,x]], + ESameTest[{a,b}, D[{a*x, b*x}, x]], + ] +}; + +Grad::usage = "`Grad[e, {var1, var2, ...}]` finds the gradient of `e` with respect to the named variables."; +Grad[e_,vars_List]:=Table[D[e,vars[[idx]]],{idx,Length[vars]}]; +Attributes[Grad] = {ReadProtected, Protected}; +Tests`Grad = { + ESimpleExamples[ + ESameTest[{-Sin[x+2 y],-2 Sin[x+2 y]}, Grad[Cos[x+2y],{x,y}]], ] }; From 73e32943aff3a67d34e04e3c09cc344e97748d94 Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 22:30:23 -0800 Subject: [PATCH 7/8] Update readme. --- README.md | 3 +++ images/jupyter_screenshot.png | Bin 0 -> 67744 bytes 2 files changed, 3 insertions(+) create mode 100644 images/jupyter_screenshot.png diff --git a/README.md b/README.md index bd4738c..d92ba6b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ Now that the kernel understands the product rule, when it later encounters a pat The term rewriting system and pattern matching engine is fairly advanced. The computer algebra system at this stage is extremely limited, but simple calculus and algebraic manipulation is certainly supported (see examples below). If you are looking for a more mature computer algebra system, please consider using Mathematica (proprietary) or Mathics (open source, Sympy-backed). +![Jupyter screenshot](/images/jupyter_screenshot.png) +This screenshot demonstrates the Jupyter notebook interface for Expreduce. This Jupyter extension can be found [here](https://github.com/mmatera/iwolfram). + # Install and run [DOWNLOAD HERE](https://github.com/corywalker/expreduce/releases/latest) diff --git a/images/jupyter_screenshot.png b/images/jupyter_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce0099eb7c31791a76eb9878c3e46af13d37adb GIT binary patch literal 67744 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 literal 0 HcmV?d00001 From c13088f574d237bb5cc07432c18838403cdb6864 Mon Sep 17 00:00:00 2001 From: cmwslw Date: Sun, 25 Nov 2018 22:31:36 -0800 Subject: [PATCH 8/8] Another README tweak. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d92ba6b..379b651 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ Now that the kernel understands the product rule, when it later encounters a pat The term rewriting system and pattern matching engine is fairly advanced. The computer algebra system at this stage is extremely limited, but simple calculus and algebraic manipulation is certainly supported (see examples below). If you are looking for a more mature computer algebra system, please consider using Mathematica (proprietary) or Mathics (open source, Sympy-backed). ![Jupyter screenshot](/images/jupyter_screenshot.png) -This screenshot demonstrates the Jupyter notebook interface for Expreduce. This Jupyter extension can be found [here](https://github.com/mmatera/iwolfram). + +(This screenshot demonstrates the Jupyter notebook interface for Expreduce. This Jupyter extension can be found [here](https://github.com/mmatera/iwolfram).) # Install and run