Skip to content

Commit

Permalink
Merge pull request #190 from corywalker/corywalker
Browse files Browse the repository at this point in the history
Corywalker
  • Loading branch information
corywalker committed Nov 21, 2018
2 parents a2d2b6e + ceb71b9 commit e689a9e
Show file tree
Hide file tree
Showing 34 changed files with 453 additions and 1,720 deletions.
3 changes: 2 additions & 1 deletion .gitattributes
@@ -1,2 +1,3 @@
expreduce/resources.go linguist-generated
expreduce/resources.go filter=lfs diff=lfs merge=lfs -text
*.m linguist-language=Mathematica
expreduce/rubi_snapshot/rubi_resources.go filter=lfs diff=lfs merge=lfs -text
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -2,6 +2,8 @@ old
calc.go
y.output
test_rubi
*.expred
.DS_Store

.idea/expreduce.iml

Expand Down
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -8,7 +8,8 @@ env:

go:
- "1.11.x"
- master
# recently this is causing a SIGSEGV in the linter.
# - master

go_import_path: github.com/corywalker/expreduce

Expand Down
10 changes: 9 additions & 1 deletion expreduce.go
Expand Up @@ -24,6 +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.")

func main() {
flag.Parse()
Expand All @@ -40,7 +41,15 @@ func main() {
go http.ListenAndServe(":8080", nil)
}

fmt.Printf("Welcome to Expreduce!\n\n")

es := expreduce.NewEvalState()
if *loadRubi {
fmt.Println("Loading Rubi snapshot for integral support. Disable with -loadrubi=false.")
es.Eval(atoms.E(atoms.S("LoadRubiBundledSnapshot")))
fmt.Println("Done loading Rubi snapshot.")
fmt.Print("\n")
}
if *debug {
es.NoInit = true
es.ClearAll()
Expand Down Expand Up @@ -91,7 +100,6 @@ func interactiveSession(es *expreduce.EvalState) {
}
defer rl.Close()

fmt.Printf("Welcome to Expreduce!\n\n")
promptNum := 1
for {
line := ""
Expand Down
19 changes: 16 additions & 3 deletions expreduce/atoms/ex_complex.go
Expand Up @@ -18,17 +18,24 @@ 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"
}
reInt, reIsInt := cmplx.Re.(*Integer)
imInt, imIsInt := cmplx.Im.(*Integer)
if reIsInt && reInt.Val.Sign() == 0 {
if imIsInt && imInt.Val.Int64() == 1 {
return "I"
return iString
}
if imIsInt && imInt.Val.Int64() == -1 {
return fmt.Sprintf("(-%v)", iString)
}
p.PreviousHead = "System`Times"
return fmt.Sprintf("(%v*I)", cmplx.Im.StringForm(p))
return fmt.Sprintf("(%v*%v)", cmplx.Im.StringForm(p), iString)
}
p.PreviousHead = "System`Plus"
return fmt.Sprintf("(%v + %v*I)", cmplx.Re.StringForm(p), cmplx.Im.StringForm(p))
return fmt.Sprintf("(%v + %v*%v)", cmplx.Re.StringForm(p), cmplx.Im.StringForm(p), iString)
}

func (cmplx *Complex) IsEqual(other expreduceapi.Ex) string {
Expand Down Expand Up @@ -134,3 +141,9 @@ func (cmplx *Complex) mulC(c *Complex) {
func (cmplx *Complex) SetNeedsEval(newVal bool) {
cmplx.needsEval = newVal
}

func (cmplx *Complex) HasReal() bool {
_, reIsFlt := cmplx.Re.(*Flt)
_, imIsFlt := cmplx.Im.(*Flt)
return reIsFlt || imIsFlt
}
6 changes: 6 additions & 0 deletions expreduce/atoms/ex_symbol.go
Expand Up @@ -27,6 +27,12 @@ func formatSymName(name string, params expreduceapi.ToStringParams) string {
if name == "Infinity" {
return "\\infty"
}
if name == "ω" {
return "\\omega"
}
if name == "Ω" {
return "\\Omega"
}
if len(name) > 1 {
return fmt.Sprintf("\\text{%v}", name)
}
Expand Down
26 changes: 25 additions & 1 deletion expreduce/atoms/order.go
@@ -1,6 +1,8 @@
package atoms

import "github.com/corywalker/expreduce/pkg/expreduceapi"
import (
"github.com/corywalker/expreduce/pkg/expreduceapi"
)

func min(x, y int) int {
if x < y {
Expand All @@ -26,6 +28,20 @@ func compareStrings(a string, b string) int64 {
return 0
}

func exprToN(e expreduceapi.Ex) expreduceapi.Ex {
asInt, isInt := e.(*Integer)
if isInt {
toReturn, _ := IntegerToFlt(asInt)
return toReturn
}
asRat, isRat := e.(*Rational)
if isRat {
toReturn, _ := RationalToFlt(asRat)
return toReturn
}
return e
}

func ExOrder(a expreduceapi.Ex, b expreduceapi.Ex) int64 {
// Support Flt, Integer, Rational, Expression, Symbol

Expand All @@ -42,6 +58,8 @@ func ExOrder(a expreduceapi.Ex, b expreduceapi.Ex) int64 {
bAsInteger, bIsInteger := b.(*Integer)
aAsRational, aIsRational := a.(*Rational)
bAsRational, bIsRational := b.(*Rational)
aAsComplex, aIsComplex := a.(*Complex)
bAsComplex, bIsComplex := b.(*Complex)

// Handle number comparisons
if aIsInteger && bIsInteger {
Expand All @@ -61,6 +79,12 @@ func ExOrder(a expreduceapi.Ex, b expreduceapi.Ex) int64 {
if bIsRational {
bAsFlt, bIsFlt = RationalToFlt(bAsRational)
}
if aIsComplex {
aAsFlt, aIsFlt = exprToN(aAsComplex.Re).(*Flt)
}
if bIsComplex {
bAsFlt, bIsFlt = exprToN(bAsComplex.Re).(*Flt)
}

if aIsFlt && bIsFlt {
initCmp := int64(bAsFlt.Val.Cmp(aAsFlt.Val))
Expand Down
6 changes: 6 additions & 0 deletions expreduce/builtin_arithmetic.go
Expand Up @@ -154,6 +154,9 @@ func getArithmeticDefinitions() (defs []Definition) {
if _, rIsReal := realPart.(*atoms.Flt); rIsReal {
return exprToN(es, res)
}
if rComplex, rIsComplex := realPart.(*atoms.Complex); rIsComplex && rComplex.HasReal() {
return exprToN(es, res)
}
return res
},
})
Expand Down Expand Up @@ -243,6 +246,9 @@ func getArithmeticDefinitions() (defs []Definition) {
if _, rIsReal := realPart.(*atoms.Flt); rIsReal {
return exprToN(es, res)
}
if rComplex, rIsComplex := realPart.(*atoms.Complex); rIsComplex && rComplex.HasReal() {
return exprToN(es, res)
}
return res
},
})
Expand Down
38 changes: 38 additions & 0 deletions expreduce/builtin_expression.go
Expand Up @@ -45,6 +45,35 @@ func leafCount(e expreduceapi.Ex) int64 {
return 1
}

func leafCountSimplify(e expreduceapi.Ex) int64 {
if asExpr, isExpr := e.(expreduceapi.ExpressionInterface); isExpr {
res := int64(0)
for _, part := range asExpr.GetParts() {
res += leafCountSimplify(part)
}
return res
}
if asInt, isInt := e.(*atoms.Integer); isInt {
if asInt.Val.Sign() == -1 {
return 2
}
}
if asCmplx, isCmplx := e.(*atoms.Complex); isCmplx {
return leafCountSimplify(asCmplx.Im) + leafCountSimplify(asCmplx.Re) + 1
}
if asRat, isRat := e.(*atoms.Rational); isRat {
val := int64(3)
if asRat.Num.Sign() == -1 {
val++
}
if asRat.Den.Sign() == -1 {
val++
}
return val
}
return 1
}

func getExpressionDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "Head",
Expand Down Expand Up @@ -160,6 +189,15 @@ func getExpressionDefinitions() (defs []Definition) {
return atoms.NewInt(leafCount(this.GetParts()[1]))
},
})
defs = append(defs, Definition{
Name: "ExpreduceLeafCountSimplify",
legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex {
if len(this.GetParts()) != 2 {
return this
}
return atoms.NewInt(leafCountSimplify(this.GetParts()[1]))
},
})
defs = append(defs, Definition{
Name: "Flat",
OmitDocumentation: true,
Expand Down
46 changes: 46 additions & 0 deletions expreduce/builtin_list.go
Expand Up @@ -393,6 +393,52 @@ func getListDefinitions() (defs []Definition) {
return toReturn
},
})
defs = append(defs, Definition{
Name: "Intersection",
legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex {
if len(this.GetParts()) == 1 {
return this
}
var firstHead expreduceapi.Ex
intersection := map[uint64]int{}
for _, part := range this.GetParts()[1:] {
expr, isExpr := part.(expreduceapi.ExpressionInterface)
if !isExpr {
return this
}
if firstHead == nil {
firstHead = expr.GetParts()[0]
} else if !atoms.IsSameQ(firstHead, expr.GetParts()[0]) {
return this
}
theseParts := map[uint64]bool{}
for _, innerPart := range expr.GetParts()[1:] {
theseParts[hashEx(innerPart)] = true
}
for hash := range theseParts {
currVal, hasVal := intersection[hash]
if !hasVal {
intersection[hash] = 1
} else {
intersection[hash] = currVal + 1
}
}
}
toReturn := atoms.E(firstHead)
added := map[uint64]bool{}
for _, part := range this.GetParts()[1].(expreduceapi.ExpressionInterface).GetParts()[1:] {
hash := hashEx(part)
_, alreadyAdded := added[hash]
intersection := intersection[hash] == this.Len()
if intersection && !alreadyAdded {
added[hash] = true
toReturn.AppendEx(part)
}
}
sort.Sort(toReturn)
return toReturn
},
})
defs = append(defs, Definition{
Name: "PadRight",
legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex {
Expand Down
10 changes: 10 additions & 0 deletions expreduce/builtin_power.go
Expand Up @@ -144,6 +144,16 @@ func getPowerDefinitions() (defs []Definition) {
return true, fmt.Sprintf("(1/Sqrt[%v])", this.GetPart(1).StringForm(nextParams))
}
}
if atoms.IsSameQ(this.GetPart(2), atoms.NewInt(-1)) {
nextParams := params
nextParams.PreviousHead = "<TOPLEVEL>"
if params.Form == "TeXForm" {
return true, fmt.Sprintf("\\frac{1}{%v}", this.GetPart(1).StringForm(nextParams))
}
if params.Form == "InputForm" {
return true, fmt.Sprintf("(1/(%v))", this.GetPart(1).StringForm(nextParams))
}
}
}
return toStringInfixAdvanced(this.GetParts()[1:], "^", "System`Power", false, "", "", params)
},
Expand Down
3 changes: 0 additions & 3 deletions expreduce/builtin_replacement.go
Expand Up @@ -97,9 +97,6 @@ func getReplacementDefinitions() (defs []Definition) {
}

rules := getValidRules(this.GetParts()[2])
if len(rules) == 0 {
return this
}
return rulesReplaceAll(this.GetParts()[1], rules, es)
},
})
Expand Down
7 changes: 7 additions & 0 deletions expreduce/builtin_rubi.go
@@ -1,3 +1,6 @@
//go:generate go run ../utils/gensnapshots/gensnapshots.go -rubi_snapshot_location=./rubi_snapshot/rubi_snapshot.expred
//go:generate go-bindata -pkg rubi_snapshot -o rubi_snapshot/rubi_resources.go -nocompress rubi_snapshot/rubi_snapshot.expred

package expreduce

func getRubiDefinitions() (defs []Definition) {
Expand All @@ -9,6 +12,10 @@ func getRubiDefinitions() (defs []Definition) {
Name: "LoadRubiSnapshot",
expreduceSpecific: true,
})
defs = append(defs, Definition{
Name: "LoadRubiBundledSnapshot",
expreduceSpecific: true,
})
defs = append(defs, Definition{
Name: "SaveRubiSnapshot",
expreduceSpecific: true,
Expand Down
23 changes: 23 additions & 0 deletions expreduce/builtin_specialsyms.go
@@ -1,5 +1,11 @@
package expreduce

import (
"fmt"

"github.com/corywalker/expreduce/pkg/expreduceapi"
)

func getSpecialSymsDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "Infinity",
Expand All @@ -16,5 +22,22 @@ func getSpecialSymsDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "E",
})
defs = append(defs, Definition{
Name: "Subscript",
toString: func(this expreduceapi.ExpressionInterface, params expreduceapi.ToStringParams) (bool, string) {
if this.Len() == 2 {
nextParams := params
nextParams.PreviousHead = "<TOPLEVEL>"
if params.Form == "TeXForm" {
return true, fmt.Sprintf(
"{%v}_{%v}",
this.GetPart(1).StringForm(nextParams),
this.GetPart(2).StringForm(nextParams),
)
}
}
return false, ""
},
})
return
}

0 comments on commit e689a9e

Please sign in to comment.