Skip to content

Commit

Permalink
Merge pull request #123 from corywalker/corywalker
Browse files Browse the repository at this point in the history
Better solve functionality.
  • Loading branch information
corywalker committed Apr 21, 2018
2 parents 7b1b5c6 + 72502fa commit 302f124
Show file tree
Hide file tree
Showing 29 changed files with 953 additions and 79 deletions.
2 changes: 2 additions & 0 deletions expreduce/builtin.go
Expand Up @@ -173,6 +173,7 @@ func GetAllDefinitions() (defs []NamedDefSet) {
defs = append(defs, NamedDefSet{"atoms", getAtomsDefinitions()})
defs = append(defs, NamedDefSet{"functional", getFunctionalDefinitions()})
defs = append(defs, NamedDefSet{"expression", GetExpressionDefinitions()})
defs = append(defs, NamedDefSet{"equationdata", GetEquationDataDefinitions()})
defs = append(defs, NamedDefSet{"solve", GetSolveDefinitions()})
defs = append(defs, NamedDefSet{"flowcontrol", GetFlowControlDefinitions()})
defs = append(defs, NamedDefSet{"list", GetListDefinitions()})
Expand All @@ -192,6 +193,7 @@ func GetAllDefinitions() (defs []NamedDefSet) {
defs = append(defs, NamedDefSet{"boolean", GetBooleanDefinitions()})
defs = append(defs, NamedDefSet{"simplify", GetSimplifyDefinitions()})
defs = append(defs, NamedDefSet{"numbertheory", GetNumberTheoryDefinitions()})
defs = append(defs, NamedDefSet{"stats", GetStatsDefinitions()})
defs = append(defs, NamedDefSet{"manip", GetManipDefinitions()})
defs = append(defs, NamedDefSet{"rubi", GetRubiDefinitions()})

Expand Down
73 changes: 65 additions & 8 deletions expreduce/builtin_arithmetic.go
Expand Up @@ -39,7 +39,32 @@ const (
FoldFnMul
)

func typedRealPart(fn FoldFn, i *Integer, r *Rational, f *Flt) Ex {
func typedRealPart(fn FoldFn, i *Integer, r *Rational, f *Flt, c *Complex) Ex {
if c != nil {
toReturn := c
if f != nil {
if fn == FoldFnAdd {
toReturn.AddF(f)
} else if fn == FoldFnMul {
toReturn.MulF(f)
}
}
if r != nil {
if fn == FoldFnAdd {
toReturn.AddR(r)
} else if fn == FoldFnMul {
toReturn.MulR(r)
}
}
if i != nil {
if fn == FoldFnAdd {
toReturn.AddI(i)
} else if fn == FoldFnMul {
toReturn.MulI(i)
}
}
return toReturn
}
if f != nil {
toReturn := f
if r != nil {
Expand Down Expand Up @@ -75,10 +100,11 @@ func typedRealPart(fn FoldFn, i *Integer, r *Rational, f *Flt) Ex {
return nil
}

func computeRealPart(fn FoldFn, e *Expression) (Ex, int) {
func computeNumericPart(fn FoldFn, e *Expression) (Ex, int) {
var foldedInt *Integer
var foldedRat *Rational
var foldedFlt *Flt
var foldedComp *Complex
for i := 1; i < len(e.Parts); i++ {
// TODO: implement short circuiting if we encounter a zero while
// multiplying.
Expand Down Expand Up @@ -124,9 +150,32 @@ func computeRealPart(fn FoldFn, e *Expression) (Ex, int) {
}
continue
}
return typedRealPart(fn, foldedInt, foldedRat, foldedFlt), i
asComp, isComp := e.Parts[i].(*Complex)
if isComp {
if foldedComp == nil {
foldedComp = asComp.DeepCopy().(*Complex)
continue
}
if fn == FoldFnAdd {
foldedComp.AddC(asComp)
} else if fn == FoldFnMul {
foldedComp.MulC(asComp)
}
continue
}
return typedRealPart(fn, foldedInt, foldedRat, foldedFlt, foldedComp), i
}
return typedRealPart(fn, foldedInt, foldedRat, foldedFlt), -1
return typedRealPart(fn, foldedInt, foldedRat, foldedFlt, foldedComp), -1
}

// Define a special NumberQ for our purposes since this logic does not support
// complex numbers yet. TODO(corywalker): fix this.
func numberQForTermCollection(e Ex) bool {
// _, ok := e.(*Complex)
// if ok {
// return false
// }
return numberQ(e)
}

func splitTerm(e Ex) (Ex, Ex, bool) {
Expand All @@ -142,7 +191,7 @@ func splitTerm(e Ex) (Ex, Ex, bool) {
if len(asTimes.Parts) < 2 {
return nil, nil, false
}
if numberQ(asTimes.Parts[1]) {
if numberQForTermCollection(asTimes.Parts[1]) {
if len(asTimes.Parts) > 2 {
return asTimes.Parts[1], NewExpression(append([]Ex{NewSymbol("System`Times")}, asTimes.Parts[2:]...)), true
}
Expand All @@ -167,7 +216,7 @@ func collectedToTerm(coeffs []Ex, vars Ex, fullPart Ex) Ex {
return fullPart
}

finalC, _ := computeRealPart(FoldFnAdd, NewExpression(append([]Ex{
finalC, _ := computeNumericPart(FoldFnAdd, NewExpression(append([]Ex{
NewSymbol("System`Plus")}, coeffs...)))

toAdd := NewExpression([]Ex{NewSymbol("System`Times")})
Expand Down Expand Up @@ -233,7 +282,7 @@ func getArithmeticDefinitions() (defs []Definition) {
}

res := this
realPart, symStart := computeRealPart(FoldFnAdd, this)
realPart, symStart := computeNumericPart(FoldFnAdd, this)
if realPart != nil {
if symStart == -1 {
return realPart
Expand All @@ -256,6 +305,10 @@ func getArithmeticDefinitions() (defs []Definition) {
return res.Parts[1]
}

// Not exactly right because of "1. + foo[1]", but close enough.
if _, rIsReal := realPart.(*Flt); rIsReal {
return exprToN(es, res)
}
return res
},
})
Expand All @@ -282,7 +335,7 @@ func getArithmeticDefinitions() (defs []Definition) {
}

res := this
realPart, symStart := computeRealPart(FoldFnMul, this)
realPart, symStart := computeNumericPart(FoldFnMul, this)
if realPart != nil {
if symStart == -1 {
return realPart
Expand Down Expand Up @@ -335,6 +388,10 @@ func getArithmeticDefinitions() (defs []Definition) {
}
}

// Not exactly right because of "1. + foo[1]", but close enough.
if _, rIsReal := realPart.(*Flt); rIsReal {
return exprToN(es, res)
}
return res
},
})
Expand Down
5 changes: 5 additions & 0 deletions expreduce/builtin_equationdata.go
@@ -0,0 +1,5 @@
package expreduce

func GetEquationDataDefinitions() (defs []Definition) {
return
}
17 changes: 16 additions & 1 deletion expreduce/builtin_functional.go
Expand Up @@ -619,7 +619,22 @@ func getFunctionalDefinitions() (defs []Definition) {
})
defs = append(defs, Definition{Name: "NestWhile"})
defs = append(defs, Definition{Name: "FixedPointList"})
defs = append(defs, Definition{Name: "FixedPoint"})
defs = append(defs, Definition{
Name: "FixedPoint",
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 3 {
return this
}

currVal := this.Parts[2]
nextVal := E(this.Parts[1], currVal).Eval(es)
for !IsSameQ(currVal, nextVal, &es.CASLogger) {
currVal = nextVal
nextVal = E(this.Parts[1], currVal).Eval(es)
}
return nextVal
},
})
defs = append(defs, Definition{
Name: "Array",
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
Expand Down
52 changes: 52 additions & 0 deletions expreduce/builtin_numbertheory.go
Expand Up @@ -5,6 +5,57 @@ import (
"math/big"
)

// Compute the prime factors of a positive n.
// TODO: use Pollard's rho algorithm and potentially have an int64 version.
func primeFactors(origN *big.Int) (factors []*big.Int) {
zero := big.NewInt(0)
one := big.NewInt(1)
if origN.Cmp(one) == 0 {
factors = append(factors, big.NewInt(1))
return
}
i := big.NewInt(2)
modRes := big.NewInt(0)
n := big.NewInt(0)
n.Set(origN)
for n.Cmp(one) != 0 {
for (modRes.Mod(n, i)).Cmp(zero) != 0 {
i.Add(i, one)
}
newFactor := big.NewInt(0)
newFactor.Set(i)
factors = append(factors, newFactor)
n.Div(n, i)
i.SetInt64(2)
}
return
}

type factorTally struct {
factor *big.Int
power uint64
}
func primeFactorsTallied(n *big.Int) (factorTallies []factorTally) {
factors := primeFactors(n)
for _, factor := range factors {
added := false
for i := range factorTallies {
if factorTallies[i].factor.Cmp(factor) == 0 {
factorTallies[i].power++
added = true
break
}
}
if !added {
factorTallies = append(factorTallies, factorTally{
factor: factor,
power: 1,
})
}
}
return
}

func GetNumberTheoryDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "PrimeQ",
Expand Down Expand Up @@ -153,5 +204,6 @@ func GetNumberTheoryDefinitions() (defs []Definition) {
defs = append(defs, Definition{Name: "EulerPhi"})
defs = append(defs, Definition{Name: "Fibonacci"})
defs = append(defs, Definition{Name: "IntegerDigits"})
defs = append(defs, Definition{Name: "Sign"})
return
}

0 comments on commit 302f124

Please sign in to comment.