Skip to content

Commit

Permalink
Expression hashing.
Browse files Browse the repository at this point in the history
  • Loading branch information
corywalker committed Jul 12, 2017
1 parent 0976649 commit 484c152
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 0 deletions.
19 changes: 19 additions & 0 deletions expreduce/builtin_system.go
Expand Up @@ -6,6 +6,13 @@ import "fmt"
import "os"
import "io/ioutil"
import "github.com/op/go-logging"
import "hash/fnv"

func hashEx(e Ex) uint64 {
h := fnv.New64a()
e.Hash(&h)
return h.Sum64()
}

func exprToN(es *EvalState, e Ex) Ex {
asInt, isInt := e.(*Integer)
Expand Down Expand Up @@ -634,5 +641,17 @@ func GetSystemDefinitions() (defs []Definition) {
Bootstrap: true,
Attributes: []string{"HoldAll"},
})
defs = append(defs, Definition{
Name: "Hash",
Usage: "`Hash[expr]` returns an integer hash of `expr`.",
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
if len(this.Parts) != 2 {
return this
}
i := big.NewInt(0)
i.SetUint64(hashEx(this.Parts[1]))
return &Integer{i}
},
})
return
}
3 changes: 3 additions & 0 deletions expreduce/cas.go
Expand Up @@ -4,6 +4,8 @@

package expreduce

import "hash"

type ToStringFnType (func(*Expression, string) (bool, string))

// A nasty global to keep track of ToString functions. TODO: Fix this.
Expand All @@ -17,4 +19,5 @@ type Ex interface {
IsEqual(b Ex, cl *CASLogger) string
DeepCopy() Ex
NeedsEval() bool
Hash(h *hash.Hash64)
}
8 changes: 8 additions & 0 deletions expreduce/ex_expression.go
Expand Up @@ -3,6 +3,7 @@ package expreduce
import "bytes"
import "math/big"
import "sort"
import "hash"

type Expression struct {
Parts []Ex
Expand Down Expand Up @@ -388,6 +389,13 @@ func (this *Expression) NeedsEval() bool {
return false
}

func (this *Expression) Hash(h *hash.Hash64) {
(*h).Write([]byte{72, 5, 244, 86, 5, 210, 69, 30})
for _, part := range this.Parts {
part.Hash(h)
}
}

func NewExpression(parts []Ex) *Expression {
return &Expression{Parts: parts}
}
Expand Down
7 changes: 7 additions & 0 deletions expreduce/ex_integer.go
Expand Up @@ -2,6 +2,7 @@ package expreduce

import "fmt"
import "math/big"
import "hash"

// Integer numbers represented by big.Int
type Integer struct {
Expand Down Expand Up @@ -52,3 +53,9 @@ func (this *Integer) NeedsEval() bool {
func NewInt(i int64) *Integer {
return &Integer{big.NewInt(i)}
}

func (this *Integer) Hash(h *hash.Hash64) {
(*h).Write([]byte{242, 99, 84, 113, 102, 46, 118, 94})
bytes, _ := this.Val.MarshalText()
(*h).Write(bytes)
}
9 changes: 9 additions & 0 deletions expreduce/ex_rational.go
Expand Up @@ -2,6 +2,7 @@ package expreduce

import "fmt"
import "math/big"
import "hash"

type Rational struct {
Num *big.Int
Expand Down Expand Up @@ -86,3 +87,11 @@ func (this *Rational) AsBigRat() *big.Rat {
func (this *Rational) NeedsEval() bool {
return false
}

func (this *Rational) Hash(h *hash.Hash64) {
(*h).Write([]byte{90, 82, 214, 51, 52, 7, 7, 33})
nBytes, _ := this.Num.MarshalText()
(*h).Write(nBytes)
dBytes, _ := this.Den.MarshalText()
(*h).Write(dBytes)
}
7 changes: 7 additions & 0 deletions expreduce/ex_real.go
Expand Up @@ -3,6 +3,7 @@ package expreduce
import "fmt"
import "math/big"
import "bytes"
import "hash"

// Floating point numbers represented by big.Float
type Flt struct {
Expand Down Expand Up @@ -66,3 +67,9 @@ func RationalToFlt(r *Rational) (*Flt, bool) {
func (this *Flt) NeedsEval() bool {
return false
}

func (this *Flt) Hash(h *hash.Hash64) {
(*h).Write([]byte{195, 244, 76, 249, 227, 115, 88, 251})
bytes, _ := this.Val.MarshalText()
(*h).Write(bytes)
}
6 changes: 6 additions & 0 deletions expreduce/ex_string.go
@@ -1,6 +1,7 @@
package expreduce

import "fmt"
import "hash"

type String struct {
Val string
Expand Down Expand Up @@ -36,3 +37,8 @@ func (this *String) DeepCopy() Ex {
thiscopy := *this
return &thiscopy
}

func (this *String) Hash(h *hash.Hash64) {
(*h).Write([]byte{102, 206, 57, 172, 207, 100, 198, 133})
(*h).Write([]byte(this.Val))
}
6 changes: 6 additions & 0 deletions expreduce/ex_symbol.go
Expand Up @@ -2,6 +2,7 @@ package expreduce

import "fmt"
import "sort"
import "hash"

// Symbols are defined by a string-based name
type Symbol struct {
Expand Down Expand Up @@ -225,3 +226,8 @@ func (this *Attributes) toStrings() []string {
func (this *Symbol) NeedsEval() bool {
return false
}

func (this *Symbol) Hash(h *hash.Hash64) {
(*h).Write([]byte{107, 10, 247, 23, 33, 221, 163, 156})
(*h).Write([]byte(this.Name))
}

0 comments on commit 484c152

Please sign in to comment.