Skip to content

Commit

Permalink
Simplify IsSameQ.
Browse files Browse the repository at this point in the history
  • Loading branch information
corywalker committed Oct 23, 2018
1 parent db35a2f commit c614702
Show file tree
Hide file tree
Showing 14 changed files with 37 additions and 55 deletions.
2 changes: 1 addition & 1 deletion expreduce/atoms/ex_expression.go
Expand Up @@ -35,7 +35,7 @@ func HeadAssertion(ex expreduceapi.Ex, head string) (*Expression, bool) {
func HeadExAssertion(ex expreduceapi.Ex, head expreduceapi.Ex, cl expreduceapi.LoggingInterface) (*Expression, bool) {
expr, isExpr := ex.(*Expression)
if isExpr {
if IsSameQ(head, expr.GetParts()[0], cl) {
if IsSameQ(head, expr.GetParts()[0]) {
return expr, true
}
}
Expand Down
40 changes: 11 additions & 29 deletions expreduce/atoms/sameq.go
Expand Up @@ -6,42 +6,24 @@ import (
"github.com/corywalker/expreduce/pkg/expreduceapi"
)

func IsSameQ(a expreduceapi.Ex, b expreduceapi.Ex, cl expreduceapi.LoggingInterface) bool {
// IsSameQ returns if two expressions are the same. It is mostly just a
// comparison of the hash values but it does include special handling for
// floats.
func IsSameQ(a expreduceapi.Ex, b expreduceapi.Ex) bool {
aFlt, aIsFlt := a.(*Flt)
bFlt, bIsFlt := b.(*Flt)
_, aIsInteger := a.(*Integer)
_, bIsInteger := b.(*Integer)
_, aIsString := a.(*String)
_, bIsString := b.(*String)
_, aIsSymbol := a.(*Symbol)
_, bIsSymbol := b.(*Symbol)
_, aIsRational := a.(*Rational)
_, bIsRational := b.(*Rational)
_, aIsComplex := a.(*Complex)
_, bIsComplex := b.(*Complex)
_, aIsExpression := a.(expreduceapi.ExpressionInterface)
_, bIsExpression := b.(expreduceapi.ExpressionInterface)

if (aIsFlt && bIsFlt) || (aIsString && bIsString) || (aIsInteger && bIsInteger) || (aIsSymbol && bIsSymbol) || (aIsRational && bIsRational) || (aIsComplex && bIsComplex) {
// a and b are identical raw types
if aIsFlt && bIsFlt {
// This is important, without it e.g. NestWhileList[(# + 3/#)/2 &, 1.0, UnsameQ, 2] never converges
// https://stackoverflow.com/questions/46136886/comparing-floats-by-ignoring-last-bit-in-golang
aVal, _ := aFlt.Val.Float64()
bVal, _ := bFlt.Val.Float64()
if aIsFlt && bIsFlt {
// This is important, without it e.g. NestWhileList[(# + 3/#)/2 &, 1.0, UnsameQ, 2] never converges
// https://stackoverflow.com/questions/46136886/comparing-floats-by-ignoring-last-bit-in-golang
aVal, _ := aFlt.Val.Float64()
bVal, _ := bFlt.Val.Float64()

if math.IsInf(aVal, 0) || math.IsInf(bVal, 0) {
return a.IsEqual(b) == "EQUAL_TRUE"
}
if !(math.IsInf(aVal, 0) || math.IsInf(bVal, 0)) {
return almostEqual(aVal, bVal)
}
return a.IsEqual(b) == "EQUAL_TRUE"
} else if aIsExpression && bIsExpression {
return a.Hash() == b.Hash()
}

// This should never happen
return false
return a.Hash() == b.Hash()
}

func almostEqual(a, b float64) bool {
Expand Down
2 changes: 1 addition & 1 deletion expreduce/builtin_combinatorics.go
Expand Up @@ -32,7 +32,7 @@ func permListContains(permList [][]expreduceapi.Ex, perm []expreduceapi.Ex, cl e
}
same := true
for i := range perm {
if !atoms.IsSameQ(perm[i], permInList[i], cl) {
if !atoms.IsSameQ(perm[i], permInList[i]) {
same = false
//break
}
Expand Down
8 changes: 4 additions & 4 deletions expreduce/builtin_comparison.go
Expand Up @@ -23,7 +23,7 @@ func extremaFunction(this expreduceapi.ExpressionInterface, fnType extremaFnType
// Previously I always set the pointer but it led to an endless
// eval loop. I think evaluation might use the pointer to make a
// "same" comparison.
if !atoms.IsSameQ(this, dst, es.GetLogger()) {
if !atoms.IsSameQ(this, dst) {
this = dst
sort.Sort(this)
}
Expand Down Expand Up @@ -133,7 +133,7 @@ func getComparisonDefinitions() (defs []Definition) {

issame := true
for i := 2; i < len(this.GetParts()); i++ {
issame = issame && atoms.IsSameQ(this.GetParts()[1], this.GetParts()[i], es.GetLogger())
issame = issame && atoms.IsSameQ(this.GetParts()[1], this.GetParts()[i])
}
if issame {
return atoms.NewSymbol("System`True")
Expand All @@ -153,7 +153,7 @@ func getComparisonDefinitions() (defs []Definition) {

for i := 1; i < len(this.GetParts()); i++ {
for j := i + 1; j < len(this.GetParts()); j++ {
if atoms.IsSameQ(this.GetParts()[i], this.GetParts()[j], es.GetLogger()) {
if atoms.IsSameQ(this.GetParts()[i], this.GetParts()[j]) {
return atoms.NewSymbol("System`False")
}
}
Expand Down Expand Up @@ -356,7 +356,7 @@ func getComparisonDefinitions() (defs []Definition) {
}
evalRes := es.Eval(atoms.E(op, lhs, rhs))
if !trueQ(evalRes, es.GetLogger()) {
if !atoms.IsSameQ(res.GetParts()[len(res.GetParts())-1], lhs, es.GetLogger()) {
if !atoms.IsSameQ(res.GetParts()[len(res.GetParts())-1], lhs) {
res.AppendEx(lhs)
}
res.AppendEx(op)
Expand Down
2 changes: 1 addition & 1 deletion expreduce/builtin_expression.go
Expand Up @@ -25,7 +25,7 @@ func flattenExpr(src expreduceapi.ExpressionInterface, dst expreduceapi.Expressi
for i := 1; i < len(src.GetParts()); i++ {
expr, isExpr := src.GetParts()[i].(expreduceapi.ExpressionInterface)
if continueFlatten && isExpr {
if atoms.IsSameQ(src.GetParts()[0], expr.GetParts()[0], cl) {
if atoms.IsSameQ(src.GetParts()[0], expr.GetParts()[0]) {
flattenExpr(expr, dst, level-1, cl)
continue
}
Expand Down
4 changes: 2 additions & 2 deletions expreduce/builtin_flowcontrol.go
Expand Up @@ -80,7 +80,7 @@ func getFlowControlDefinitions() (defs []Definition) {
if len(this.GetParts()) != 3 {
return this
}
isTrue := atoms.IsSameQ(es.Eval(this.GetParts()[1].DeepCopy()), atoms.NewSymbol("System`True"), es.GetLogger())
isTrue := atoms.IsSameQ(es.Eval(this.GetParts()[1].DeepCopy()), atoms.NewSymbol("System`True"))
for isTrue {
tmpRes := es.Eval(this.GetParts()[2].DeepCopy())
retVal, isReturn := tryReturnValue(tmpRes, nil, es)
Expand All @@ -90,7 +90,7 @@ func getFlowControlDefinitions() (defs []Definition) {
if isBreak(tmpRes) {
return atoms.S("Null")
}
isTrue = atoms.IsSameQ(es.Eval(this.GetParts()[1].DeepCopy()), atoms.NewSymbol("System`True"), es.GetLogger())
isTrue = atoms.IsSameQ(es.Eval(this.GetParts()[1].DeepCopy()), atoms.NewSymbol("System`True"))
}

return atoms.NewSymbol("System`Null")
Expand Down
2 changes: 1 addition & 1 deletion expreduce/builtin_functional.go
Expand Up @@ -610,7 +610,7 @@ func getFunctionalDefinitions() (defs []Definition) {

currVal := this.GetParts()[2]
nextVal := es.Eval(atoms.E(this.GetParts()[1], currVal))
for !atoms.IsSameQ(currVal, nextVal, es.GetLogger()) {
for !atoms.IsSameQ(currVal, nextVal) {
currVal = nextVal
nextVal = es.Eval(atoms.E(this.GetParts()[1], currVal))
}
Expand Down
8 changes: 4 additions & 4 deletions expreduce/builtin_list.go
Expand Up @@ -341,7 +341,7 @@ func getListDefinitions() (defs []Definition) {
if firstHead == nil {
firstHead = expr.GetParts()[0]
allParts = atoms.NewExpression([]expreduceapi.Ex{firstHead})
} else if !atoms.IsSameQ(firstHead, expr.GetParts()[0], es.GetLogger()) {
} else if !atoms.IsSameQ(firstHead, expr.GetParts()[0]) {
return this
}
allParts.AppendExArray(expr.GetParts()[1:])
Expand All @@ -350,7 +350,7 @@ func getListDefinitions() (defs []Definition) {
toReturn := atoms.NewExpression([]expreduceapi.Ex{firstHead})
var lastEx expreduceapi.Ex
for _, part := range allParts.GetParts()[1:] {
if lastEx == nil || !atoms.IsSameQ(lastEx, part, es.GetLogger()) {
if lastEx == nil || !atoms.IsSameQ(lastEx, part) {
lastEx = part
toReturn.AppendEx(part)
}
Expand All @@ -375,7 +375,7 @@ func getListDefinitions() (defs []Definition) {
if firstHead == nil {
firstHead = expr.GetParts()[0]
continue
} else if !atoms.IsSameQ(firstHead, expr.GetParts()[0], es.GetLogger()) {
} else if !atoms.IsSameQ(firstHead, expr.GetParts()[0]) {
return this
}
for _, excludedPart := range expr.GetParts()[1:] {
Expand Down Expand Up @@ -636,7 +636,7 @@ func getListDefinitions() (defs []Definition) {
if len(res.GetParts()) == 0 {
res.AppendExArray(expr.GetParts())
} else {
if !atoms.IsSameQ(expr.GetParts()[0], res.GetParts()[0], es.GetLogger()) {
if !atoms.IsSameQ(expr.GetParts()[0], res.GetParts()[0]) {
return this
}
res.AppendExArray(expr.GetParts()[1:])
Expand Down
2 changes: 1 addition & 1 deletion expreduce/builtin_replacement.go
Expand Up @@ -150,7 +150,7 @@ func getReplacementDefinitions() (defs []Definition) {

es.Infof("In ReplaceRepeated. New expr: %v", newEx)

if atoms.IsSameQ(oldEx, newEx, es.GetLogger()) {
if atoms.IsSameQ(oldEx, newEx) {
isSame = true
}
oldEx = newEx
Expand Down
6 changes: 3 additions & 3 deletions expreduce/eval.go
Expand Up @@ -37,7 +37,7 @@ func (es *EvalState) Eval(expr expreduceapi.Ex) expreduceapi.Ex {
func (es *EvalState) evalComplex(this *atoms.Complex) expreduceapi.Ex {
this.Re = es.Eval(this.Re)
this.Im = es.Eval(this.Im)
if atoms.IsSameQ(this.Im, atoms.NewInt(0), es.GetLogger()) {
if atoms.IsSameQ(this.Im, atoms.NewInt(0)) {
return this.Re
}
this.SetNeedsEval(false)
Expand Down Expand Up @@ -161,7 +161,7 @@ func (es *EvalState) evalExpression(this *atoms.Expression) expreduceapi.Ex {
currEx.DeepCopy(),
})

if !atoms.IsSameQ(es.GetTrace().GetParts()[len(es.GetTrace().GetParts())-1], toAppend, es.GetLogger()) {
if !atoms.IsSameQ(es.GetTrace().GetParts()[len(es.GetTrace().GetParts())-1], toAppend) {
//fmt.Printf("Beginning: appending %v\n", toAppend.StringForm("FullForm"))
es.GetTrace().AppendEx(toAppend)
}
Expand Down Expand Up @@ -212,7 +212,7 @@ func (es *EvalState) evalExpression(this *atoms.Expression) expreduceapi.Ex {
if hasLegacyEvalFn {
currEx = legacyEvalFn(curr, es)
// TODO: I could potentially have the legacyevalfn return this.
unchanged = atoms.IsSameQ(currEx, curr, es.GetLogger())
unchanged = atoms.IsSameQ(currEx, curr)
}
if unchanged {
theRes, isDefined, def := es.GetDef(headStr, curr)
Expand Down
4 changes: 2 additions & 2 deletions expreduce/evalstate.go
Expand Up @@ -499,11 +499,11 @@ func (es *EvalState) Define(lhs expreduceapi.Ex, rhs expreduceapi.Ex) {
for _, dv := range es.defined.GetDef(name).Downvalues {
existingRule := dv.Rule
existingLHS := existingRule.GetParts()[1]
if atoms.IsSameQ(existingLHS, heldLHS, &es.CASLogger) {
if atoms.IsSameQ(existingLHS, heldLHS) {
es.defined.LockKey(name)
existingRHSCond := maskNonConditional(existingRule.GetParts()[2])
newRHSCond := maskNonConditional(rhs)
if atoms.IsSameQ(existingRHSCond, newRHSCond, &es.CASLogger) {
if atoms.IsSameQ(existingRHSCond, newRHSCond) {
dv.Rule.GetParts()[2] = rhs
es.defined.UnlockKey(name)
return
Expand Down
6 changes: 3 additions & 3 deletions expreduce/matcher/blank.go
Expand Up @@ -49,7 +49,7 @@ func isBlankTypeCapturing(e expreduceapi.Ex, target expreduceapi.Ex, head expred
if len(parts) < 2 {
matchesHead = true
} else {
matchesHead = atoms.IsSameQ(head, parts[1], cl)
matchesHead = atoms.IsSameQ(head, parts[1])
}
cl.Debugf("%v", matchesHead)
if matchesHead {
Expand All @@ -63,7 +63,7 @@ func isBlankTypeCapturing(e expreduceapi.Ex, target expreduceapi.Ex, head expred
pm.lazyMakeMap()
pm.patternDefined[sAsSymbol.Name] = target
}
if !atoms.IsSameQ(toMatch, target, cl) {
if !atoms.IsSameQ(toMatch, target) {
return false, pm
}
}
Expand All @@ -87,7 +87,7 @@ func isBlankTypeCapturing(e expreduceapi.Ex, target expreduceapi.Ex, head expred
if len(parts) < 2 {
return true, pm
}
return atoms.IsSameQ(head, parts[1], cl), pm
return atoms.IsSameQ(head, parts[1]), pm
}
return false, pm
}
Expand Down
4 changes: 2 additions & 2 deletions expreduce/matcher/matchq.go
Expand Up @@ -171,7 +171,7 @@ func NewMatchIter(a expreduceapi.Ex, b expreduceapi.Ex, pm *PDManager, es expred
verbatimOp, opExpr, isVerbatimOp := atoms.OperatorAssertion(b, "System`Verbatim")
if aIsExpression && isVerbatimOp {
if len(opExpr.GetParts()) == 2 {
if atoms.IsSameQ(aExpression.GetParts()[0], opExpr.GetParts()[1], es.GetLogger()) {
if atoms.IsSameQ(aExpression.GetParts()[0], opExpr.GetParts()[1]) {
b = atoms.NewExpression(append([]expreduceapi.Ex{opExpr.GetParts()[1]}, verbatimOp.GetParts()[1:]...))
bExpression, bIsExpression = b.(expreduceapi.ExpressionInterface)
forceOrdered = true
Expand Down Expand Up @@ -265,7 +265,7 @@ func NewMatchIter(a expreduceapi.Ex, b expreduceapi.Ex, pm *PDManager, es expred

if !assumingHead {
if aIsFlt || aIsInteger || aIsString || aIsSymbol || aIsRational || aIsComplex {
if atoms.IsSameQ(a, b, es.GetLogger()) {
if atoms.IsSameQ(a, b) {
return &dummyMatchIter{nil}, true
}
return nil, false
Expand Down
2 changes: 1 addition & 1 deletion expreduce/matcher/pdmanager.go
Expand Up @@ -119,7 +119,7 @@ func defineSequence(lhs parsedForm, sequence []expreduceapi.Ex, pm *PDManager, s

if pm.patternDefined != nil {
defined, ispd := pm.patternDefined[lhs.patSym.Name]
if ispd && !atoms.IsSameQ(defined, attemptDefine, es.GetLogger()) {
if ispd && !atoms.IsSameQ(defined, attemptDefine) {
es.Debugf("patterns do not match! continuing.")
return false
}
Expand Down

0 comments on commit c614702

Please sign in to comment.