Franck Pommereau

use unique hashtable implementation

// Python3 dicts ported to Go, inspired from a Python version at
// https://code.activestate.com/recipes/578375/
package dicts
import (
"bytes"
"fmt"
"reflect"
"math/bits"
)
//
// hash any value
//
const _FREE int64 = -1
const _DUMMY int64 = -2
func Hash (value interface{}) uint64 {
h, err := doHash(value, nil)
if err != nil {
panic(err)
}
i := int64(h)
if i < 0 {
return uint64(-i)
} else {
return uint64(i)
}
}
//
// compare any values
//
type Equatable interface {
Eq (interface{}) bool
}
func Eq (a, b interface{}) bool {
i, ok := a.(Equatable)
if ok {
return i.Eq(b)
}
return reflect.DeepEqual(a, b)
}
//
// dict type
//
type DictItem struct {
Key *interface{}
Value *interface{}
hash uint64
}
type Dict struct {
indices []int64
itemlist []DictItem
used uint64
filled uint64
keyhash uint64
}
func (self *Dict) Clear () {
self.indices = []int64{_FREE, _FREE, _FREE, _FREE, _FREE, _FREE, _FREE, _FREE}
self.itemlist = make([]DictItem, 0)
self.used = 0
self.filled = 0
self.keyhash = 0
}
type copyfunc func(interface{})interface{}
func (self Dict) Copy (copiers ...copyfunc) Dict {
d := Dict{
make([]int64, len(self.indices)),
make([]DictItem, len(self.itemlist)),
self.used,
self.filled,
self.keyhash}
copy(d.indices, self.indices)
if len(copiers) == 0 {
copy(d.itemlist, self.itemlist)
} else if len(copiers) == 1 {
cpk := copiers[0]
for i := uint64(0); i < self.used; i++ {
item := &self.itemlist[i]
k := cpk(*(item.Key))
d.itemlist[i] = DictItem{&k, item.Value, item.hash}
}
} else if len(copiers) == 2 {
cpk := copiers[0]
cpv := copiers[1]
for i := uint64(0); i < self.used; i++ {
item := &self.itemlist[i]
k := cpk(*(item.Key))
v := cpv(*(item.Value))
d.itemlist[i] = DictItem{&k, &v, item.hash}
}
} else {
panic("at most two copiers are allowed")
}
return d
}
func MakeDict (items ...DictItem) Dict {
d := Dict{}
d.Clear()
for _, i := range items {
d.Set(*(i.Key), *(i.Value))
}
return d
}
func (self Dict) Len () uint64 {
return self.used
}
const _PERTURB_SHIFT uint64 = 5
type probe struct {
i uint64
index uint64
perturb uint64
mask uint64
}
func (self Dict) first_probe (hashvalue uint64) (uint64, probe) {
m := uint64(len(self.indices)) - 1
p := probe{hashvalue & m, hashvalue, hashvalue, m}
return p.i, p
}
func (self *probe) next () uint64 {
self.index = 5 * self.i + self.perturb + 1
self.i = self.index & self.mask
self.perturb >>= _PERTURB_SHIFT
return self.i
}
func (self Dict) lookup (key interface{}, hashvalue uint64) (int64, uint64) {
var freeslot uint64
var fsempty bool = true
if self.filled >= uint64(len(self.indices)) {
panic("no open slot")
}
i, p := self.first_probe(hashvalue)
for ; true; i = p.next() {
index := self.indices[i]
switch index {
case _FREE :
if fsempty {
return _FREE, i
} else {
return _DUMMY, freeslot
}
case _DUMMY :
if fsempty {
fsempty = false
freeslot = i
}
default :
item := self.itemlist[index]
if item.Key == &key || item.hash == hashvalue && Eq(*(item.Key), key) {
return index, i
}
}
}
panic("unreachable code has been reached")
}
func (self Dict) Get (key interface{}) *interface{} {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return nil
}
return self.itemlist[index].Value
}
func (self Dict) GetItem (key interface{}) *DictItem {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return nil
}
return &self.itemlist[index]
}
func (self Dict) Fetch (key interface{}, fallback interface{}) *interface{} {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return &fallback
} else {
return self.itemlist[index].Value
}
}
func (self *Dict) resize (size uint64) {
s := uint64(1) << uint64(bits.Len64(size))
self.indices = make([]int64, s)
for i := uint64(0); i < s; i++ {
self.indices[i] = _FREE
}
for index, item := range self.itemlist {
for i, p := self.first_probe(item.hash); true; i = p.next() {
if self.indices[i] == _FREE {
self.indices[i] = int64(index)
break
}
}
}
self.filled = self.used
}
func (self *Dict) Set (key interface{}, value interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
self.indices[i] = int64(self.used)
self.itemlist = append(self.itemlist, DictItem{&key, &value, hashvalue})
self.used++
if index == _FREE {
self.filled++
if self.filled * 3 > uint64(len(self.indices)) * 2 {
self.resize(4 * self.used)
}
}
self.keyhash += hashvalue
} else {
self.itemlist[index] = DictItem{&key, &value, hashvalue}
}
}
func (self *Dict) Del (key interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
return
}
self.indices[i] = _DUMMY
self.used--
if uint64(index) != self.used {
lastitem := self.itemlist[self.used]
lastindex, j := self.lookup(*(lastitem.Key), lastitem.hash)
if lastindex < 0 || i == j {
panic("inconsistent Dict internal state")
}
self.indices[j] = index
self.itemlist[index] = lastitem
}
self.keyhash -= hashvalue
}
type DictIterator struct {
i uint64
d *Dict
}
func (self *DictIterator) Next () *DictItem {
self.i++
if self.i >= self.d.used {
return nil
} else {
return &(self.d.itemlist[self.i])
}
}
func (self Dict) Iter () (DictIterator, *DictItem) {
it := DictIterator{0, &self}
if self.used == 0 {
return it, nil
} else {
return it, &(self.itemlist[0])
}
}
func (self Dict) Has (key interface{}) bool {
index, _ := self.lookup(key, Hash(key))
return index >= 0
}
func (self *Dict) Pop () DictItem {
if self.used == 0 {
panic("cannot Pop from empty Dict")
}
item := self.itemlist[self.used-1]
self.Del(*(item.Key))
self.keyhash -= item.hash
return item
}
func (self Dict) Hash () uint64 {
var h uint64 = 1959494633841095838 + self.keyhash
for i := uint64(0); i < self.used; i++ {
h += 5 * Hash(*(self.itemlist[i].Value)) + 1
}
return h
}
func (self Dict) Eq (other interface{}) bool {
d, ok := other.(Dict)
if ok {
if self.Len() != d.Len() {
return false
} else if self.keyhash != d.keyhash {
return false
}
for i := uint64(0); i < self.used; i++ {
value := d.Get(*(self.itemlist[i].Key))
if value == nil {
return false
} else if ! Eq(*(self.itemlist[i].Value), *(value)) {
return false
}
}
return true
} else {
return false
}
}
//
//
//
func (self Dict) String () string {
buf := bytes.NewBufferString("{")
for i := uint64(0); i < self.used; i++ {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(fmt.Sprintf("%#v", *(self.itemlist[i].Key)))
buf.WriteString(": ")
buf.WriteString(fmt.Sprintf("%#v", *(self.itemlist[i].Value)))
}
buf.WriteString("}")
return buf.String()
}
func (self DictItem) String () string {
return fmt.Sprintf("DictItem{%s}",
fmt.Sprintf("%#v, %#v, %#v",
fmt.Sprint(*(self.Key)),
fmt.Sprint(*(self.Value)),
self.hash))
}
func (self Dict) ShowStructure () {
for i:=0; i < 50; i++ {
fmt.Print("=")
}
fmt.Println()
fmt.Println(self)
fmt.Println("Indices:", self.indices)
fmt.Println("Items:")
for i := uint64(0); i < self.used; i++ {
fmt.Printf(" [%d] %s\n", i, self.itemlist[i])
}
for i:=0; i < 50; i++ {
fmt.Print("-")
}
fmt.Println()
}
// Python3 dicts ported to Go, inspired from a Python version at
// https://code.activestate.com/recipes/578375/
package dicts
import (
"bytes"
"fmt"
"math/bits"
)
//
// set type
//
type SetItem struct {
Key *interface{}
hash uint64
}
type Set struct {
indices []int64
itemlist []SetItem
used uint64
filled uint64
keyhash uint64
}
func (self *Set) Clear () {
self.indices = []int64{_FREE, _FREE, _FREE, _FREE, _FREE, _FREE, _FREE, _FREE}
self.itemlist = make([]SetItem, 0)
self.used = 0
self.filled = 0
self.keyhash = 0
}
func (self Set) Copy (copiers ...copyfunc) Set {
s := Set{
make([]int64, len(self.indices)),
make([]SetItem, len(self.itemlist)),
self.used,
self.filled,
self.keyhash}
copy(s.indices, self.indices)
if len(copiers) == 0 {
copy(s.itemlist, self.itemlist)
} else if len(copiers) == 1 {
cpk := copiers[0]
for index, item := range self.itemlist {
k := cpk(*(item.Key))
s.itemlist[index] = SetItem{&k, item.hash}
}
} else {
panic("at most one copier is allowed")
}
return s
}
func MakeSet (items ...interface{}) Set {
s := Set{}
s.Clear()
for _, i := range items {
s.Add(i)
}
return s
}
func (self Set) Len () uint64 {
return self.used
}
type sprobe struct {
i uint64
perturb uint64
}
func (self Set) first_probe (hashvalue uint64) (uint64, probe) {
m := uint64(len(self.indices)) - 1
p := probe{hashvalue & m, hashvalue, hashvalue, m}
return p.i, p
}
func (self Set) lookup (key interface{}, hashvalue uint64) (int64, uint64) {
var freeslot uint64
var fsempty bool = true
if self.filled >= uint64(len(self.indices)) {
panic("no open slot")
}
i, p := self.first_probe(hashvalue)
for ; true; i = p.next() {
index := self.indices[i]
switch index {
case _FREE :
if fsempty {
return _FREE, i
} else {
return _DUMMY, freeslot
}
case _DUMMY :
if fsempty {
fsempty = false
freeslot = i
}
default :
item := self.itemlist[index]
if item.Key == &key || item.hash == hashvalue && Eq(*(item.Key), key) {
return index, i
}
}
}
panic("unreachable code has been reached")
}
func (self Set) Get (key interface{}) *interface{} {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return nil
}
return self.itemlist[index].Key
}
func (self Set) Fetch (key interface{}, fallback interface{}) *interface{} {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return &fallback
} else {
return self.itemlist[index].Key
}
}
func (self *Set) resize (size uint64) {
s := uint64(1) << uint64(bits.Len64(size))
self.indices = make([]int64, s)
for i := uint64(0); i < s; i++ {
self.indices[i] = _FREE
}
for index, item := range self.itemlist {
for i, p := self.first_probe(item.hash); true; i = p.next() {
if self.indices[i] == _FREE {
self.indices[i] = int64(index)
break
}
}
}
self.filled = self.used
}
func (self *Set) Add (key interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
self.indices[i] = int64(self.used)
self.itemlist = append(self.itemlist, SetItem{&key, hashvalue})
self.used++
if index == _FREE {
self.filled++
if self.filled * 3 > uint64(len(self.indices)) * 2 {
self.resize(4 * self.used)
}
}
self.keyhash += hashvalue
} else {
self.itemlist[index] = SetItem{&key, hashvalue}
}
}
func (self *Set) Del (key interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
return
}
self.indices[i] = _DUMMY
self.used--
if uint64(index) != self.used {
lastitem := self.itemlist[self.used]
lastindex, j := self.lookup(*(lastitem.Key), lastitem.hash)
if lastindex < 0 || i == j {
panic("inconsistent Set internal state")
}
self.indices[j] = index
self.itemlist[index] = lastitem
}
self.keyhash -= hashvalue
}
type SetIterator struct {
i uint64
s *Set
}
func (self *SetIterator) Next () *SetItem {
self.i++
if self.i >= self.s.used {
return nil
} else {
return &(self.s.itemlist[self.i])
}
}
func (self Set) Iter () (SetIterator, *SetItem) {
it := SetIterator{0, &self}
if self.used == 0 {
return it, nil
} else {
return it, &(self.itemlist[0])
}
}
func (self Set) Has (key interface{}) bool {
index, _ := self.lookup(key, Hash(key))
return index >= 0
}
func (self *Set) Pop () SetItem {
if self.used == 0 {
panic("cannot Pop from empty Set")
}
item := self.itemlist[self.used-1]
self.Del(*(item.Key))
self.keyhash -= item.hash
return item
}
func (self Set) Hash () uint64 {
return self.keyhash
}
func (self Set) Eq (other interface{}) bool {
s, ok := other.(Set)
if ok {
if self.Len() != s.Len() {
return false
} else if self.keyhash != s.keyhash {
return false
}
for i := uint64(0); i < self.used; i++ {
value := s.Get(*(self.itemlist[i].Key))
if value == nil {
return false
}
}
return true
} else {
return false
}
}
//
//
//
func (self Set) String () string {
buf := bytes.NewBufferString("{")
for i := uint64(0); i < self.used; i++ {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(fmt.Sprintf("%#v", *(self.itemlist[i].Key)))
}
buf.WriteString("}")
return buf.String()
}
func (self SetItem) String () string {
return fmt.Sprintf("SetItem{%s}",
fmt.Sprintf("%#v, %#v",
fmt.Sprint(*(self.Key)),
self.hash))
}
func (self Set) ShowStructure () {
for i:=0; i < 50; i++ {
fmt.Print("=")
}
fmt.Println()
fmt.Println(self)
fmt.Println("Indices:", self.indices)
fmt.Println("Items:")
for i := uint64(0); i < self.used; i++ {
fmt.Printf(" [%d] %s\n", i, self.itemlist[i])
}
for i:=0; i < 50; i++ {
fmt.Print("-")
}
fmt.Println()
}
......@@ -23,7 +23,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package dicts
package zn
import (
"encoding/binary"
......@@ -143,10 +143,6 @@ type visitOpts struct {
StructField string
}
type Hashable interface {
Hash () uint64
}
func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
// Call method Hash() is any
......
......@@ -2,47 +2,46 @@ package zn
import "fmt"
import "bytes"
import "dicts"
type Marking struct {
d *dicts.Dict
i int
}
func (self *Marking) SetId (id int) {
self.i = id
}
func (self Marking) GetId () int {
return self.i
Id int
h *Hashtable
}
func MakeMarking (id ...int) Marking {
d := dicts.MakeDict()
h := MakeHashtable(true)
if len(id) == 0 {
return Marking{&d, -1}
return Marking{-1, &h}
} else if len(id) == 1 {
return Marking{&d, id[0]}
return Marking{id[0], &h}
} else {
panic("at most one id expected")
}
}
func (self *Marking) SetId (id int) {
self.Id = id
}
func (self Marking) GetId () int {
return self.Id
}
func (self Marking) Hash () uint64 {
return self.d.Hash()
return self.h.Hash() + 8635519453209983077
}
func (self Marking) Eq (other interface{}) bool {
m, ok := other.(Marking)
if ok {
return self.d.Eq(*(m.d))
return self.h == m.h || self.h.Eq(*(m.h))
} else {
return false
}
}
func (self Marking) Has (p string) bool {
return self.d.Has(p)
return self.h.Has(p)
}
//### a := zn.MakeMarking()
......@@ -82,10 +81,9 @@ func (self Marking) Has (p string) bool {
func (self Marking) Set (p string, tokens ...interface{}) {
if len(tokens) == 0 {
self.d.Del(p)
self.h.Del(p)
} else {
m := MakeMset(tokens...)
self.d.Set(p, m)
self.h.Put(p, MakeMset(tokens...))
}
}
......@@ -105,11 +103,11 @@ func (self Marking) Set (p string, tokens ...interface{}) {
//=== true
func (self Marking) Update (p string, tokens Mset) {
if self.Has(p) {
m := self.Get(p)
m.Add(tokens)
k, m := self.h.Get(p)
if k != nil {
(*m).(Mset).Add(tokens)
} else {
self.d.Set(p, tokens.Copy())
self.h.Put(p, tokens.Copy())
}
}
......@@ -123,17 +121,9 @@ func (self Marking) Update (p string, tokens Mset) {
//... a.Eq(b)
//=== true
func copykey (k interface{}) interface{} {
return k
}
func copyval (v interface{}) interface{} {
return v.(Mset).Copy()
}
func (self Marking) Copy () Marking {
dict := self.d.Copy(copykey, copyval)
return Marking{&dict, self.i}
h := self.h.Copy()
return Marking{self.Id, &h}
}
//### a := zn.MakeMarking()
......@@ -182,7 +172,12 @@ func (self Marking) Copy () Marking {
//=== false
func (self Marking) Get (p string) Mset {
return (*(self.d.Fetch(p, MakeMset()))).(Mset)
k, m := self.h.Get(p)
if k == nil {
return MakeMset()
} else {
return (*m).(Mset)
}
}
//### a := zn.MakeMarking()
......@@ -204,8 +199,11 @@ func (self Marking) Get (p string) Mset {
//=== true
func (self Marking) NotEmpty (places ...string) bool {
for _, key := range places {
if self.Get(key).Empty() {
for _, p := range places {
k, m := self.h.Get(p)
if k == nil {
return false
} else if (*m).(Mset).Empty() {
return false
}
}
......@@ -258,12 +256,15 @@ func (self Marking) Add (other Marking) Marking {
//=== true
func (self Marking) Sub (other Marking) Marking {
for iter, p, m := other.Iter(); p != nil; p, m = iter.Next() {
mine := self.Get(*p)
if m.Geq(mine) {
self.d.Del(*p)
} else {
mine.Sub(*m)
for iter, place, right := other.Iter(); place != nil; place, right = iter.Next() {
k, left := self.h.Get(*place)
if k != nil {
m := (*left).(Mset)
if right.Geq(m) {
self.h.Del(*place)
} else {
m.Sub(*right)
}
}
}
return self
......@@ -337,28 +338,28 @@ func (self Marking) Geq (other Marking) bool {
//=== false
type MarkingIterator struct {
iter *dicts.DictIterator
iter HashtableIterator
}
func (self MarkingIterator) Next () (*string, *Mset) {
next := self.iter.Next()
if next == nil {
func (self *MarkingIterator) Next () (*string, *Mset) {
key, val := self.iter.Next()
if key == nil {
return nil, nil
} else {
p := (*next.Key).(string)
m := (*next.Value).(Mset)
p := (*key).(string)
m := (*val).(Mset)
return &p, &m
}
}
func (self Marking) Iter () (MarkingIterator, *string, *Mset) {
iter, item := self.d.Iter()
myiter := MarkingIterator{&iter}
if item == nil {
iter, key, val := self.h.Iter()
myiter := MarkingIterator{iter}
if key == nil {
return myiter, nil, nil
} else {
p := (*item.Key).(string)
m := (*item.Value).(Mset)
p := (*key).(string)
m := (*val).(Mset)
return myiter, &p, &m
}
}
......@@ -383,19 +384,17 @@ func (self Marking) Iter () (MarkingIterator, *string, *Mset) {
func (self Marking) String () string {
buf := bytes.NewBufferString("")
if self.i >= 0 {
buf.WriteString(fmt.Sprintf("[%d] ", self.i))
}
buf.WriteString("{")
comma := false
for iter, p, m := self.Iter(); p != nil; p, m = iter.Next() {
if comma {
buf.WriteString(", ")
} else {
comma = true
}
buf.WriteString(fmt.Sprintf(`"%s": %s`, *p, *m))
if self.Id >= 0 {
buf.WriteString(fmt.Sprintf("[%d] %s", self.Id, *(self.h)))
} else {
buf.WriteString(fmt.Sprintf("%s", *(self.h)))
}
buf.WriteString("}")
return buf.String()
}
//### a := zn.MakeMarking()
//... a.Set("p1", 1, 2, 2, 3)
//... b := a.Copy()
//... b.Update("p1", zn.MakeMset(42))
//... a.Eq(b)
//=== false
......
......@@ -2,20 +2,24 @@ package zn
import "fmt"
import "bytes"
import "dicts"
type Mset struct {
d *dicts.Dict
h *Hashtable
size uint64
}
func (self Mset) Hash () uint64 {
return self.d.Hash()
return self.h.Hash()
}
func (self Mset) Eq (other interface{}) bool {
m, ok := other.(Mset)
if ok {
return self.d.Eq(*(m.d))
if self.size != m.size {
return false
} else {
return self.h == m.h || self.h.Eq(*(m.h))
}
} else {
return false
}
......@@ -25,11 +29,15 @@ func (self Mset) Eq (other interface{}) bool {
//+++ zn.MakeMset(1, 2, 2, 3, 3, 3).Hash() == zn.MakeMset(3, 2, 1, 3, 2, 3).Hash()
func MakeMset (values ...interface{}) Mset {
dict := dicts.MakeDict()
mset := Mset{&dict}
ht := MakeHashtable(true)
mset := Mset{&ht, uint64(len(values))}
for _, elt := range values {
count := (*mset.d.Fetch(elt, uint64(0))).(uint64)
mset.d.Set(elt, count + 1)
k, v := ht.Get(elt)
if k == nil {
ht.Put(elt, uint64(1))
} else {
ht.Put(elt, (*v).(uint64) + 1)
}
}
return mset
}
......@@ -41,29 +49,30 @@ func MakeMset (values ...interface{}) Mset {
//--- zn.MakeMset(1, 1, 3).Eq(zn.MakeMset(1, 1, 1))
//--- zn.MakeMset(1, 1, 1).Eq(zn.MakeMset(2, 2, 2))
func (self Mset) Copy () Mset {
dict := self.d.Copy()
return Mset{&dict}
func (self Mset) Copy () interface{} {
h := self.h.Copy()
return Mset{&h, self.size}
}
//+++ zn.MakeMset(1, 2, 2, 3, 3, 3).Copy().Eq(zn.MakeMset(1, 2, 2, 3, 3, 3))
func (self Mset) Len () uint64 {
count := uint64(0)
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
count += (*(item.Value)).(uint64)
}
return count
return self.size
}
//+++ zn.MakeMset(1, 2, 2, 3, 3, 3).Len() == 6
//+++ zn.MakeMset().Len() == 0
func (self Mset) Add (other Mset) Mset {
for iter, item := other.d.Iter(); item != nil; item = iter.Next() {
count := (*(self.d.Fetch(*(item.Key), uint64(0)))).(uint64)
self.d.Set(*(item.Key), count + (*(item.Value)).(uint64))
for iter, key, val := other.h.Iter(); key != nil; key, val = iter.Next() {
k, v := self.h.Get(*key)
if k == nil {
self.h.Put(*key, (*val).(uint64))
} else {
self.h.Put(*key, (*v).(uint64) + (*val).(uint64))
}
}
self.size += other.size
return self
}
......@@ -74,13 +83,18 @@ func (self Mset) Add (other Mset) Mset {
//=== true
func (self Mset) Sub (other Mset) Mset {
for iter, item := other.d.Iter(); item != nil; item = iter.Next() {
left := (*(self.d.Fetch(*(item.Key), uint64(0)))).(uint64)
right := (*(item.Value)).(uint64)
if left <= right {
self.d.Del(*(item.Key))
} else {
self.d.Set(*(item.Key), left - right)
for iter, key, val := other.h.Iter(); key != nil; key, val = iter.Next() {
k, v := self.h.Get(*key)
if k != nil {
left := (*v).(uint64)
right := (*val).(uint64)
if left <= right {
self.h.Del(*key)
self.size -= left
} else {
self.h.Put(*key, left - right)
self.size -= right
}
}
}
return self
......@@ -99,9 +113,14 @@ func (self Mset) Sub (other Mset) Mset {
//=== true
func (self Mset) Geq (other Mset) bool {
for iter, item := other.d.Iter(); item != nil; item = iter.Next() {
count := (*(self.d.Fetch(*(item.Key), uint64(0)))).(uint64)
if count < (*item.Value).(uint64) {
if self.size < other.size {
return false
}
for iter, key, val := other.h.Iter(); key != nil; key, val = iter.Next() {
k, v := self.h.Get(*key)
if k == nil {
return false
} else if (*v).(uint64) < (*val).(uint64) {
return false
}
}
......@@ -118,7 +137,7 @@ func (self Mset) Geq (other Mset) bool {
//--- zn.MakeMset().Geq(zn.MakeMset(1))
func (self Mset) Empty () bool {
return self.d.Len() == 0
return self.size == 0
}
//+++ zn.MakeMset().Empty()
......@@ -126,7 +145,12 @@ func (self Mset) Empty () bool {
//--- zn.MakeMset(1, 2).Empty()
func (self Mset) Count (value interface{}) uint64 {
return (*(self.d.Fetch(value, uint64(0)))).(uint64)
k, v := self.h.Get(value)
if k == nil {
return 0
} else {
return (*v).(uint64)
}
}
//### zn.MakeMset(1, 2, 2, 3, 3, 3).Count(1)
......@@ -139,42 +163,48 @@ func (self Mset) Count (value interface{}) uint64 {
//=== 3
type MsetIterator struct {
iter dicts.DictIterator
iter HashtableIterator
dup bool
count uint64
current *dicts.DictItem
key *interface{}
}
func (self *MsetIterator) Next () *interface{} {
if self.current == nil {
var val *interface{}
if self.key == nil {
return nil
} else if self.count == 0 {
self.current = self.iter.Next()
if self.current == nil {
self.key, val = self.iter.Next()
if self.key == nil {
return nil
} else if self.dup {
self.count = (*(self.current.Value)).(uint64) - 1
self.count = (*(val)).(uint64) - 1
}
} else if self.dup {
self.count--
}
return self.current.Key
return self.key
}
func (self Mset) Iter () (MsetIterator, *interface{}) {
iter, item := self.d.Iter()
myiter := MsetIterator{iter, false, 0, item}
if item == nil {
iter, key, _ := self.h.Iter()
myiter := MsetIterator{iter, false, 0, key}
if key == nil {
return myiter, nil
} else {
return myiter, item.Key
return myiter, key
}
}
func (self Mset) IterDup () (MsetIterator, *interface{}) {
iter, item := self.d.Iter()
myiter := MsetIterator{iter, true, (*(item.Value)).(uint64) - 1, item}
return myiter, item.Key
iter, key, val := self.h.Iter()
myiter := MsetIterator{iter, true, 0, key}
if key == nil {
return myiter, nil
} else {
myiter.count = (*val).(uint64) - 1
return myiter, key
}
}
//### a := zn.MakeMset(1, 2, 2, 3, 3, 3)
......@@ -216,20 +246,11 @@ type mapfunc func (interface{}, uint64) (interface{}, uint64)
func (self Mset) Map (f mapfunc) Mset {
copy := MakeMset()
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
k := *(item.Key)
v := (*(item.Value)).(uint64)
for iter, key, val := self.h.Iter(); key != nil; key, val = iter.Next() {
k := *key
v := (*val).(uint64)
k, v = f(k, v)
copy.d.Set(k, v)
copy.h.Put(k, v)
}
return copy
}
//### a := zn.MakeMset(1, 2, 2)
//... b := a.Map(func (v interface{}, n uint64) (interface{}, uint64) {return v.(int)+1, n})
//... b.Eq(zn.MakeMset(2, 3, 3))
//=== true
func (self Mset) ShowStructure () {
self.d.ShowStructure()
}
......
package zn
import "dicts"
type Set struct {
s *dicts.Set
h *Hashtable
}
//*** a := zn.MakeMarking()
......@@ -14,19 +12,19 @@ type Set struct {
//*** c.Set("p3", 3)
func MakeSet (markings ...Marking) Set {
set := dicts.MakeSet()
h := MakeHashtable(false)
for _, m := range markings {
set.Add(m)
h.Put(m)
}
return Set{&set}
return Set{&h}
}
func (self Set) Empty () bool {
return self.s.Len() == 0
return self.h.Len() == 0
}
func (self Set) NotEmpty () bool {
return self.s.Len() > 0
return self.h.Len() > 0
}
//+++ zn.MakeSet().Empty()
......@@ -35,7 +33,7 @@ func (self Set) NotEmpty () bool {
//+++ zn.MakeSet(a).NotEmpty()
func (self Set) Len () uint64 {
return self.s.Len()
return self.h.Len()
}
//+++ zn.MakeSet().Len() == 0
......@@ -43,7 +41,7 @@ func (self Set) Len () uint64 {
//+++ zn.MakeSet(a, a).Len() == 1
func (self *Set) Add (m Marking) {
self.s.Add(m)
self.h.Put(m)
}
//### s := zn.MakeSet(a, b)
......@@ -57,7 +55,7 @@ func (self *Set) Add (m Marking) {
//=== 3
func (self Set) Get (m Marking) (bool, Marking) {
k := self.s.Get(m)
k, _ := self.h.Get(m)
if k == nil {
return false, MakeMarking()
} else {
......@@ -72,7 +70,7 @@ func (self Set) Get (m Marking) (bool, Marking) {
//=== true [42] {"p1": [1]}
func (self Set) Has (m Marking) bool {
return self.s.Has(m)
return self.h.Has(m)
}
//+++ zn.MakeSet(a, b).Has(a)
......@@ -80,25 +78,25 @@ func (self Set) Has (m Marking) bool {
//--- zn.MakeSet(a, b).Has(c)
type SetIterator struct {
i dicts.SetIterator
i HashtableIterator
}
func (self *SetIterator) Next () *Marking {
n := self.i.Next()
n, _ := self.i.Next()
if n == nil {
return nil
} else {
m := (*(n.Key)).(Marking)
m := (*n).(Marking)
return &m
}
}
func (self Set) Iter () (SetIterator, *Marking) {
i, f := self.s.Iter()
i, f, _ := self.h.Iter()
if f == nil {
return SetIterator{i}, nil
} else {
m := (*(f.Key)).(Marking)
m := (*f).(Marking)
return SetIterator{i}, &m
}
}
......
// Python3 dicts ported to Go, inspired from a Python version at
// https://code.activestate.com/recipes/578375/
package zn
import (
"reflect"
"bytes"
"fmt"
"math/bits"
)
//
// generic hash / compare
//
type Hashable interface {
Hash () uint64
}
func Hash (value interface{}) uint64 {
h, err := doHash(value, nil)
if err != nil {
panic(err)
}
i := int64(h)
if i < 0 {
return uint64(-i)
} else {
return uint64(i)
}
}
type Equatable interface {
Eq (interface{}) bool
}
func Eq (a, b interface{}) bool {
i, ok := a.(Equatable)
if ok {
return i.Eq(b)
}
return reflect.DeepEqual(a, b)
}
type Copyable interface {
Copy() interface{}
}
func Copy (a interface{}) interface{} {
i, ok := a.(Copyable)
if ok {
return i.Copy()
} else {
return a
}
}
//
// items
//
type _Slot struct {
hash uint64
key interface{}
}
//
// hashtables
//
type Hashtable struct {
indices []int64
slots []_Slot
payloads []interface{}
haspl bool
used uint64
filled uint64
keyhash uint64
}
const _FREE int64 = -1
const _DUMMY int64 = -2
func MakeHashtable (payloads bool) Hashtable {
return Hashtable{
[]int64{_FREE, _FREE, _FREE, _FREE, _FREE, _FREE, _FREE, _FREE},
make([]_Slot, 0),
make([]interface{}, 0),
payloads,
0,
0,
0}
}
func (self *Hashtable) Clear () {
*self = MakeHashtable(self.haspl)
}
func (self Hashtable) Copy () Hashtable {
ht := Hashtable{
make([]int64, len(self.indices)),
make([]_Slot, len(self.slots)),
make([]interface{}, len(self.payloads)),
self.haspl,
self.used,
self.filled,
self.keyhash}
copy(ht.indices, self.indices)
if self.haspl {
for i := uint64(0); i < self.used; i++ {
slot := &(self.slots[i])
ht.slots[i] = _Slot{slot.hash, Copy(slot.key)}
ht.payloads[i] = Copy(self.payloads[i])
}
} else {
for i := uint64(0); i < self.used; i++ {
slot := &(self.slots[i])
ht.slots[i] = _Slot{slot.hash, Copy(slot.key)}
}
}
return ht
}
func (self Hashtable) Len () uint64 {
return self.used
}
type hGen struct {
hash uint64
index uint64
perturb uint64
mask uint64
}
func (self Hashtable) probe (hashvalue uint64) (uint64, hGen) {
m := uint64(len(self.indices)) - 1
g := hGen{hashvalue & m, hashvalue, hashvalue, m}
return g.hash, g
}
const _PERTURB_SHIFT uint64 = 5
func (self *hGen) next () uint64 {
self.index = 5 * self.index + self.perturb + 1
self.hash = self.index & self.mask
self.perturb >>= _PERTURB_SHIFT
return self.hash
}
func (self Hashtable) lookup (key interface{}, hashvalue uint64) (int64, uint64) {
var freeslot uint64
var fsempty bool = true
if self.filled >= uint64(len(self.indices)) {
panic("no open slot")
}
for i, g := self.probe(hashvalue); true; i = g.next() {
index := self.indices[i]
switch index {
case _FREE :
if fsempty {
return _FREE, i
} else {
return _DUMMY, freeslot
}
case _DUMMY :
if fsempty {
fsempty = false
freeslot = i
}
default :
if Eq(self.slots[index].key, key) {
return index, i
}
}
}
panic("unreachable code has been reached")
}
func (self Hashtable) Get (key interface{}) (*interface{}, *interface{}) {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return nil, nil
} else if self.haspl {
return &(self.slots[index].key), &(self.payloads[index])
} else {
return &(self.slots[index].key), nil
}
}
func (self *Hashtable) resize (size uint64) {
s := uint64(1) << uint64(bits.Len64(size))
self.indices = make([]int64, s)
for i := uint64(0); i < s; i++ {
self.indices[i] = _FREE
}
for n := uint64(0); n < self.used; n++ {
for i, p := self.probe(self.slots[n].hash); true; i = p.next() {
if self.indices[i] == _FREE {
self.indices[i] = int64(n)
break
}
}
}
self.filled = self.used
}
func (self *Hashtable) Put (keyval ...interface{}) {
if self.haspl {
if len(keyval) != 2 {
panic("two items expected (key and payload)")
}
} else if len(keyval) != 1 {
panic("one item expected (key)")
}
key := keyval[0]
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
self.indices[i] = int64(self.used)
self.slots = append(self.slots, _Slot{hashvalue, key})
if self.haspl {
self.payloads = append(self.payloads, keyval[1])
}
self.used++
if index == _FREE {
self.filled++
if self.filled * 3 > uint64(len(self.indices)) * 2 {
self.resize(4 * self.used)
}
}
self.keyhash += hashvalue
} else {
self.slots[index] = _Slot{hashvalue, key}
if self.haspl {
self.payloads[index] = keyval[1]
}
}
}
func (self *Hashtable) Del (key interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
return
}
self.indices[i] = _DUMMY
self.used--
if uint64(index) != self.used {
lastslot := &self.slots[self.used]
lastindex, j := self.lookup(lastslot.key, lastslot.hash)
if lastindex < 0 || i == j {
panic("inconsistent Hashtable internal state")
}
self.indices[j] = index
self.slots[index] = *lastslot
if self.haspl{
self.payloads[index] = self.payloads[self.used]
}
}
self.slots = self.slots[:self.used]
if self.haspl {
self.payloads = self.payloads[:self.used]
}
self.keyhash -= hashvalue
}
type HashtableIterator struct {
i uint64
h *Hashtable
}
func (self *HashtableIterator) Next () (*interface{}, *interface{}) {
self.i++
if self.i >= self.h.used {
return nil, nil
} else if self.h.haspl {
return &(self.h.slots[self.i].key), &(self.h.payloads[self.i])
} else {
return &(self.h.slots[self.i].key), nil
}
}
func (self Hashtable) Iter () (HashtableIterator, *interface{}, *interface{}) {
it := HashtableIterator{0, &self}
if self.used == 0 {
return it, nil, nil
} else if self.haspl {
return it, &(self.slots[0].key), &(self.payloads[0])
} else {
return it, &(self.slots[0].key), nil
}
}
func (self Hashtable) Has (key interface{}) bool {
index, _ := self.lookup(key, Hash(key))
return index >= 0
}
func (self *Hashtable) Pop () (*interface{}, *interface{}) {
var payload *interface{}
var slot *_Slot
if self.used == 0 {
return nil, nil
} else if self.haspl {
slot = &(self.slots[self.used-1])
payload = &(self.payloads[self.used-1])
} else {
slot = &(self.slots[self.used-1])
payload = nil
}
self.Del(slot.key)
self.keyhash -= slot.hash
return &(slot.key), payload
}
func (self Hashtable) Hash () uint64 {
if self.haspl {
h := self.keyhash
for i := uint64(0); i < self.used; i++ {
h += 5 * Hash(self.payloads[i])
}
return h
} else {
return self.keyhash
}
}
func (self Hashtable) Eq (other interface{}) bool {
ht, ok := other.(Hashtable)
if ok {
if self.used != ht.used {
return false
} else if self.keyhash != ht.keyhash {
return false
} else if &self.slots == &ht.slots {
return true
}
for i := uint64(0); i < self.used; i++ {
if self.haspl {
if &self.slots[i] == &ht.slots[i] && &self.payloads[i] != &ht.payloads[i] {
return true
}
} else {
if &self.slots[i] == &ht.slots[i] {
return true
}
}
key, val := ht.Get(self.slots[i].key)
if key == nil {
return false
} else if self.haspl && ! Eq(self.payloads[i], *val) {
return false
}
}
return true
} else {
return false
}
}
//
//
//
func (self Hashtable) String () string {
buf := bytes.NewBufferString("{")
for i := uint64(0); i < self.used; i++ {
if i > 0 {
buf.WriteString(", ")
}
if self.haspl {
buf.WriteString(fmt.Sprintf("%#v: %s", self.slots[i].key, self.payloads[i]))
} else {
buf.WriteString(fmt.Sprintf("%#v", self.slots[i].key))
}
}
buf.WriteString("}")
return buf.String()
}