├── .gitignore ├── LICENSE ├── README.md ├── bit ├── pack.go ├── pack_test.go ├── unpack.go └── unpack_test.go ├── event ├── event.go └── event_test.go ├── id ├── id.go └── id_test.go ├── stamp.go └── stamp_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | *.iws 4 | *.ipr 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Stephan Heinze 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ITC 2 | === 3 | 4 | [![Build Status](https://drone.io/github.com/fgrid/itc/status.png)](https://drone.io/github.com/fgrid/itc/latest) [![Coverage Status](https://coveralls.io/repos/fgrid/itc/badge.png?branch=master)](https://coveralls.io/r/fgrid/itc?branch=master) [![Stories in Ready](https://badge.waffle.io/fgrid/itc.svg?label=ready&title=Ready)](http://waffle.io/fgrid/itc) [![GoDoc](https://godoc.org/github.com/fgrid/itc?status.png)](https://godoc.org/github.com/fgrid/itc) [![Go Walker](http://gowalker.org/api/v1/badge)](https://gowalker.org/github.com/fgrid/itc) 5 | 6 | This project is based on the [paper](http://gsd.di.uminho.pt/members/cbm/ps/itc2008.pdf) 'Interval Tree Clocks: 7 | A Logical Clock for Dynamic Systems' by Paulo Sergio Almeida, Carlos Baquero and Victor Fonte. 8 | 9 | -------------------------------------------------------------------------------- /bit/pack.go: -------------------------------------------------------------------------------- 1 | package bit 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | ) 8 | 9 | type packEntry struct { 10 | value, size uint32 11 | } 12 | 13 | type Pack struct { 14 | bitLength uint32 15 | entries []packEntry 16 | packed []byte 17 | } 18 | 19 | func NewPack() *Pack { 20 | return &Pack{entries: make([]packEntry, 0), packed: make([]byte, 4)} 21 | } 22 | 23 | func (p *Pack) Push(value, size uint32) { 24 | p.entries = append(p.entries, packEntry{value: value, size: size}) 25 | freeBits := uint32(8*len(p.packed)) - p.bitLength 26 | index := p.bitLength / 32 27 | if freeBits >= size { 28 | shift := freeBits - size 29 | v := binary.BigEndian.Uint32(p.packed[index:]) | (value << shift) 30 | binary.BigEndian.PutUint32(p.packed[index:], v) 31 | } else { 32 | buf := make([]byte, 4) 33 | low := value 34 | if freeBits > 0 { 35 | high := value>>size - freeBits 36 | v := binary.BigEndian.Uint32(p.packed[index:]) | high 37 | binary.BigEndian.PutUint32(p.packed[index:], v) 38 | low = ((value << freeBits) >> freeBits) 39 | } else { 40 | shift := 32 - size 41 | low = (value << shift) 42 | } 43 | binary.BigEndian.PutUint32(buf, low) 44 | p.packed = append(p.packed[:], buf[:]...) 45 | } 46 | p.bitLength += size 47 | } 48 | 49 | func (p *Pack) Pack() []byte { 50 | return p.packed 51 | } 52 | 53 | func (p *Pack) PackedString() string { 54 | var b bytes.Buffer 55 | for i, w := range p.packed { 56 | remainingBits := int32(p.bitLength) - int32(i*8) 57 | if remainingBits < 0 { 58 | break 59 | } 60 | if remainingBits < 8 { 61 | b.WriteString(fmt.Sprintf("%0*b", int(remainingBits), w>>uint(8-remainingBits))) 62 | } else { 63 | b.WriteString(fmt.Sprintf("%0*b", int(8), w)) 64 | } 65 | } 66 | return b.String() 67 | } 68 | 69 | func (p *Pack) String() string { 70 | var buf bytes.Buffer 71 | buf.WriteString("<<") 72 | for i, entry := range p.entries { 73 | if i > 0 { 74 | buf.WriteString(", ") 75 | } 76 | buf.WriteString(fmt.Sprintf("%d:%d", entry.value, entry.size)) 77 | } 78 | buf.WriteString(">>") 79 | return buf.String() 80 | } 81 | 82 | func Enc(n, B uint32, packer *Pack) *Pack { 83 | max := uint32(1) << uint32(B) 84 | if n < max { 85 | packer.Push(uint32(0), uint32(1)) 86 | packer.Push(uint32(n), uint32(B)) 87 | } else { 88 | packer.Push(uint32(1), uint32(1)) 89 | Enc(n-max, B+1, packer) 90 | } 91 | return packer 92 | } 93 | -------------------------------------------------------------------------------- /bit/pack_test.go: -------------------------------------------------------------------------------- 1 | package bit 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ExamplePackSimple() { 8 | bp := NewPack() 9 | bp.Push(uint32(2), uint32(3)) 10 | bp.Push(uint32(0), uint32(1)) 11 | bp.Push(uint32(1), uint32(2)) 12 | source, dest := exercisePack(bp) 13 | fmt.Printf("Pack(%s) = %s\n", source, dest) 14 | // Output: 15 | // Pack(<<2:3, 0:1, 1:2>>) = 010001 16 | } 17 | 18 | func ExamplePackLarger() { 19 | bp := NewPack() 20 | bp.Push(uint32(2), uint32(2)) 21 | bp.Push(uint32(2), uint32(2)) 22 | bp.Push(uint32(2), uint32(2)) 23 | bp.Push(uint32(2), uint32(2)) 24 | bp.Push(uint32(2), uint32(2)) 25 | source, dest := exercisePack(bp) 26 | fmt.Printf("Pack(%s) = %s\n", source, dest) 27 | // Output: 28 | // Pack(<<2:2, 2:2, 2:2, 2:2, 2:2>>) = 1010101010 29 | } 30 | 31 | func ExamplePackUneven() { 32 | bp := NewPack() 33 | bp.Push(uint32(6), uint32(3)) 34 | bp.Push(uint32(6), uint32(3)) 35 | bp.Push(uint32(6), uint32(3)) 36 | source, dest := exercisePack(bp) 37 | fmt.Printf("Pack(%s) = %s\n", source, dest) 38 | // Output: 39 | // Pack(<<6:3, 6:3, 6:3>>) = 110110110 40 | } 41 | 42 | func exercisePack(bp *Pack) (string, string) { 43 | return bp.String(), bp.PackedString() 44 | } 45 | -------------------------------------------------------------------------------- /bit/unpack.go: -------------------------------------------------------------------------------- 1 | package bit 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | type UnPack struct { 8 | index uint32 9 | packed []byte 10 | } 11 | 12 | func NewUnPack(packed []byte) *UnPack { 13 | return &UnPack{packed: packed} 14 | } 15 | 16 | func (bup *UnPack) Pop(size uint32) (value uint32) { 17 | byteIndex := (bup.index / 8) / 4 18 | offset := bup.index % 32 19 | value = binary.BigEndian.Uint32(bup.packed[byteIndex : byteIndex+4]) 20 | shift := 32 - size 21 | value = uint32(value<<(offset)) >> shift 22 | if offset > shift { 23 | remain := offset - shift 24 | low := binary.BigEndian.Uint32(bup.packed[byteIndex+4:byteIndex+8]) >> (32 - remain) 25 | value = value | low 26 | } 27 | bup.index += size 28 | return 29 | } 30 | 31 | func Dec(B uint32, unpacker *UnPack) uint32 { 32 | max := uint32(1) << uint32(B) 33 | if unpacker.Pop(uint32(1)) == 0 { 34 | return unpacker.Pop(B) 35 | } 36 | return max + Dec(B+1, unpacker) 37 | } 38 | -------------------------------------------------------------------------------- /bit/unpack_test.go: -------------------------------------------------------------------------------- 1 | package bit 2 | 3 | import "fmt" 4 | 5 | func ExamplePopSimple() { 6 | bup := NewUnPack([]byte{0x44, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00}) 7 | fmt.Printf("Base = 010001\n") 8 | fmt.Printf("Pop(3) = %d\n", bup.Pop(uint32(3))) 9 | fmt.Printf("Pop(1) = %d\n", bup.Pop(uint32(1))) 10 | fmt.Printf("Pop(2) = %d\n", bup.Pop(uint32(2))) 11 | fmt.Printf("Pop(25) = %d\n", bup.Pop(uint32(25))) 12 | fmt.Printf("Pop(2) = %d\n", bup.Pop(uint32(2))) 13 | // Output: 14 | // Base = 010001 15 | // Pop(3) = 2 16 | // Pop(1) = 0 17 | // Pop(2) = 1 18 | // Pop(25) = 0 19 | // Pop(2) = 3 20 | } 21 | -------------------------------------------------------------------------------- /event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fgrid/itc/bit" 6 | ) 7 | 8 | type Event struct { 9 | Value uint32 10 | Left, Right *Event 11 | IsLeaf bool 12 | } 13 | 14 | const ( 15 | zero = uint32(0) 16 | one = uint32(1) 17 | two = uint32(2) 18 | three = uint32(3) 19 | ) 20 | 21 | func New() *Event { 22 | return NewLeaf(zero) 23 | } 24 | 25 | func NewLeaf(value uint32) *Event { 26 | return &Event{Value: value, IsLeaf: true} 27 | } 28 | 29 | func NewEmptyNode(value uint32) *Event { 30 | return &Event{Value: value, IsLeaf: false, Left: New(), Right: New()} 31 | } 32 | 33 | func NewNode(value, left, right uint32) *Event { 34 | return &Event{Value: value, IsLeaf: false, Left: NewLeaf(left), Right: NewLeaf(right)} 35 | } 36 | 37 | func (e *Event) Clone() *Event { 38 | result := New() 39 | result.IsLeaf = e.IsLeaf 40 | result.Value = e.Value 41 | if e.Left != nil { 42 | result.Left = e.Left.Clone() 43 | } 44 | if e.Right != nil { 45 | result.Right = e.Right.Clone() 46 | } 47 | return result 48 | } 49 | 50 | func (e *Event) Equals(o *Event) bool { 51 | return (e == nil && o == nil) || 52 | ((e.IsLeaf == o.IsLeaf) && 53 | (e.Value == o.Value) && 54 | e.Left.Equals(o.Left) && 55 | e.Right.Equals(o.Right)) 56 | } 57 | 58 | func (e *Event) Norm() *Event { 59 | if e.IsLeaf { 60 | return e 61 | } 62 | if e.Left.IsLeaf && e.Right.IsLeaf && e.Left.Value == e.Right.Value { 63 | return NewLeaf(e.Value + e.Left.Value) 64 | } 65 | m := Min(e.Left.Min(), e.Right.Min()) 66 | e.Left = e.Left.Norm().sink(m) 67 | e.Right = e.Right.Norm().sink(m) 68 | return e.lift(m) 69 | } 70 | 71 | func (e *Event) lift(value uint32) *Event { 72 | result := e.Clone() 73 | result.Value += value 74 | return result 75 | } 76 | 77 | func (e *Event) Max() uint32 { 78 | if e.IsLeaf { 79 | return e.Value 80 | } 81 | return e.Value + Max(e.Left.Max(), e.Right.Max()) 82 | } 83 | 84 | func (e *Event) Min() uint32 { 85 | if e.IsLeaf { 86 | return e.Value 87 | } 88 | return e.Value + Min(e.Left.Min(), e.Right.Min()) 89 | } 90 | 91 | func (e *Event) sink(value uint32) *Event { 92 | result := e.Clone() 93 | result.Value -= value 94 | return result 95 | } 96 | 97 | func (e *Event) String() string { 98 | if e.IsLeaf { 99 | return fmt.Sprintf("%d", e.Value) 100 | } 101 | return fmt.Sprintf("(%d, %s, %s)", e.Value, e.Left, e.Right) 102 | } 103 | 104 | // ---------- 105 | func Join(e1, e2 *Event) *Event { 106 | if e1.IsLeaf && e2.IsLeaf { 107 | return NewLeaf(Max(e1.Value, e2.Value)) 108 | } 109 | if e1.IsLeaf { 110 | return Join(NewEmptyNode(e1.Value), e2) 111 | } 112 | if e2.IsLeaf { 113 | return Join(e1, NewEmptyNode(e2.Value)) 114 | } 115 | if e1.Value > e2.Value { 116 | return Join(e2, e1) 117 | } 118 | e := NewEmptyNode(e1.Value) 119 | e.Left = Join(e1.Left, e2.Left.lift(e2.Value-e1.Value)) 120 | e.Right = Join(e1.Right, e2.Right.lift(e2.Value-e1.Value)) 121 | return e.Norm() 122 | } 123 | 124 | func LEQ(e1, e2 *Event) bool { 125 | if e1.IsLeaf { 126 | return e1.Value <= e2.Value 127 | } 128 | if e2.IsLeaf { 129 | return (e1.Value <= e2.Value) && 130 | LEQ(e1.Left.lift(e1.Value), e2) && 131 | LEQ(e1.Right.lift(e1.Value), e2) 132 | } 133 | return (e1.Value <= e2.Value) && 134 | LEQ(e1.Left.lift(e1.Value), e2.Left.lift(e2.Value)) && 135 | LEQ(e1.Right.lift(e1.Value), e2.Right.lift(e2.Value)) 136 | } 137 | 138 | func Max(n1, n2 uint32) uint32 { 139 | if n1 > n2 { 140 | return n1 141 | } 142 | return n2 143 | } 144 | 145 | func Min(n1, n2 uint32) uint32 { 146 | if n1 < n2 { 147 | return n1 148 | } 149 | return n2 150 | } 151 | 152 | func (e Event) Pack(bp *bit.Pack) { 153 | if e.IsLeaf { 154 | bp.Push(one, one) 155 | bit.Enc(uint32(e.Value), two, bp) 156 | return 157 | } 158 | 159 | bp.Push(zero, one) 160 | if e.Value == 0 { 161 | if e.Left.IsLeaf && e.Left.Value == 0 { 162 | bp.Push(zero, two) 163 | e.Right.Pack(bp) 164 | return 165 | } 166 | if e.Right.IsLeaf && e.Right.Value == 0 { 167 | bp.Push(one, two) 168 | e.Left.Pack(bp) 169 | return 170 | } 171 | bp.Push(two, two) 172 | e.Left.Pack(bp) 173 | e.Right.Pack(bp) 174 | return 175 | } 176 | 177 | bp.Push(three, two) 178 | if e.Left.IsLeaf && e.Left.Value == 0 { 179 | bp.Push(zero, one) 180 | bp.Push(zero, one) 181 | NewLeaf(e.Value).Pack(bp) 182 | e.Right.Pack(bp) 183 | return 184 | } 185 | if e.Right.IsLeaf && e.Right.Value == 0 { 186 | bp.Push(zero, one) 187 | bp.Push(one, one) 188 | NewLeaf(e.Value).Pack(bp) 189 | e.Left.Pack(bp) 190 | return 191 | } 192 | bp.Push(one, one) 193 | NewLeaf(e.Value).Pack(bp) 194 | e.Left.Pack(bp) 195 | e.Right.Pack(bp) 196 | return 197 | } 198 | 199 | func UnPack(bup *bit.UnPack) *Event { 200 | if bup.Pop(one) == 1 { 201 | return NewLeaf(bit.Dec(two, bup)) 202 | } 203 | e := NewNode(zero, zero, zero) 204 | switch bup.Pop(two) { 205 | case 0: 206 | e.Right = UnPack(bup) 207 | case 1: 208 | e.Left = UnPack(bup) 209 | case 2: 210 | e.Left = UnPack(bup) 211 | e.Right = UnPack(bup) 212 | case 3: 213 | if bup.Pop(one) == 0 { 214 | if bup.Pop(one) == 0 { 215 | bup.Pop(one) 216 | e.Value = bit.Dec(two, bup) 217 | e.Right = UnPack(bup) 218 | } else { 219 | bup.Pop(one) 220 | e.Value = bit.Dec(two, bup) 221 | e.Left = UnPack(bup) 222 | } 223 | } else { 224 | bup.Pop(one) 225 | e.Value = bit.Dec(two, bup) 226 | e.Left = UnPack(bup) 227 | e.Right = UnPack(bup) 228 | } 229 | } 230 | return e 231 | } 232 | -------------------------------------------------------------------------------- /event/event_test.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fgrid/itc/bit" 6 | "testing" 7 | ) 8 | 9 | func TestEventAsLeaf(t *testing.T) { 10 | e := NewLeaf(one) 11 | if !e.IsLeaf { 12 | t.Error("event is not recognized as leaf after \"setAsLeaf()\"") 13 | } 14 | if e.Left != nil || e.Right != nil { 15 | t.Error("Left or Right is filled - should not in a leaf") 16 | } 17 | } 18 | 19 | func TestEventAsNode(t *testing.T) { 20 | e := NewNode(one, one, one) 21 | if e.IsLeaf { 22 | t.Error("event is not recognized as node after \"setAsNode()\"") 23 | } 24 | if e.Left == nil || e.Right == nil { 25 | t.Error("Left or Right is not filled - should in a node") 26 | } 27 | } 28 | 29 | func TestEventLeafStringer(t *testing.T) { 30 | eventString := NewLeaf(zero).String() 31 | if eventString != "0" { 32 | t.Errorf("leaf event did not serialize as expected %q", eventString) 33 | } 34 | } 35 | 36 | func TestEventNodeStringer(t *testing.T) { 37 | event := NewNode(zero, one, two) 38 | eventString := event.String() 39 | if eventString != "(0, 1, 2)" { 40 | t.Errorf("node event did not serialize as expected %q", eventString) 41 | } 42 | } 43 | 44 | func ExampleLiftLeafEvent() { 45 | event := NewLeaf(uint32(4)) 46 | sourceString := event.String() 47 | fmt.Printf("lift(%s, 3) = %s", sourceString, event.lift(three)) 48 | // Output: 49 | // lift(4, 3) = 7 50 | } 51 | 52 | func ExampleLiftNodeEvent() { 53 | event := NewNode(one, two, three) 54 | sourceString := event.String() 55 | fmt.Printf("lift(%s, 3) = %s", sourceString, event.lift(three)) 56 | // Output: 57 | // lift((1, 2, 3), 3) = (4, 2, 3) 58 | } 59 | 60 | func ExampleSinkLeafEvent() { 61 | event := NewLeaf(uint32(4)) 62 | sourceString := event.String() 63 | fmt.Printf("sink(%s, 3) = %s", sourceString, event.sink(three)) 64 | // Output: 65 | // sink(4, 3) = 1 66 | } 67 | 68 | func ExampleSinkNodeEvent() { 69 | event := NewNode(uint32(4), two, three) 70 | sourceString := event.String() 71 | fmt.Printf("sink(%s, 3) = %s", sourceString, event.sink(three)) 72 | // Output: 73 | // sink((4, 2, 3), 3) = (1, 2, 3) 74 | } 75 | 76 | func ExampleNormLeafEvent() { 77 | event := NewLeaf(uint32(4)) 78 | sourceString := event.String() 79 | fmt.Printf("Norm(%s) = %s", sourceString, event.Norm()) 80 | // Output: 81 | // Norm(4) = 4 82 | } 83 | 84 | func ExampleNormNodeEventWithLeaves() { 85 | event := NewNode(two, one, one) 86 | sourceString := event.String() 87 | fmt.Printf("Norm(%s) = %s", sourceString, event.Norm()) 88 | // Output: 89 | // Norm((2, 1, 1)) = 3 90 | } 91 | 92 | func ExampleNormNodeEventWithNodes() { 93 | event := NewNode(two, one, one) 94 | event.Left = NewNode(two, one, zero) 95 | event.Right = NewLeaf(three) 96 | sourceString := event.String() 97 | fmt.Printf("Norm(%s) = %s", sourceString, event.Norm()) 98 | // Output: 99 | // Norm((2, (2, 1, 0), 3)) = (4, (0, 1, 0), 1) 100 | } 101 | 102 | func ExampleMinOfLeafEvent() { 103 | event := NewLeaf(uint32(4)) 104 | fmt.Printf("Min(%s) = %d", event, event.Min()) 105 | // Output: 106 | // Min(4) = 4 107 | } 108 | 109 | func ExampleJoinLeafEvents() { 110 | e1 := NewLeaf(uint32(7)) 111 | e2 := NewLeaf(uint32(9)) 112 | fmt.Printf("Join(%s, %s) = %s\n", e1, e2, Join(e1, e2)) 113 | // Output: 114 | // Join(7, 9) = 9 115 | } 116 | 117 | func ExampleJoinNodeEvents() { 118 | e1 := NewNode(one, two, three) 119 | e2 := NewNode(uint32(4), uint32(5), uint32(6)) 120 | fmt.Printf("Join(%s, %s) = %s\n", e1, e2, Join(e1, e2)) 121 | // Output: 122 | // Join((1, 2, 3), (4, 5, 6)) = (9, 0, 1) 123 | } 124 | 125 | func ExampleEqualsNilEvents() { 126 | var e1, e2 *Event 127 | fmt.Printf("e1 = %q, e2 = %q => e1.Equals(e2) = %t", e1, e2, e1.Equals(e2)) 128 | // Output: 129 | // e1 = , e2 = => e1.Equals(e2) = true 130 | } 131 | 132 | func ExampleLeqLeafEvents() { 133 | e1 := NewLeaf(one) 134 | e2 := NewLeaf(two) 135 | s2 := NewLeaf(two) 136 | 137 | fmt.Printf("LEQ(%s, %s) = %t\n", e1, e2, LEQ(e1, e2)) 138 | fmt.Printf("LEQ(%s, %s) = %t\n", e2, e1, LEQ(e2, e1)) 139 | fmt.Printf("LEQ(%s, %s) = %t\n", e2, s2, LEQ(e2, s2)) 140 | 141 | // Output: 142 | // LEQ(1, 2) = true 143 | // LEQ(2, 1) = false 144 | // LEQ(2, 2) = true 145 | } 146 | 147 | func ExampleLeqLeftLeaf() { 148 | e1 := NewLeaf(one) 149 | e2 := NewNode(two, one, one) 150 | e3 := NewLeaf(three) 151 | e4 := NewNode(one, one, one) 152 | 153 | fmt.Printf("LEQ(%s, %s) = %t\n", e1, e2, LEQ(e1, e2)) 154 | fmt.Printf("LEQ(%s, %s) = %t\n", e1, e4, LEQ(e1, e4)) 155 | fmt.Printf("LEQ(%s, %s) = %t\n", e3, e2, LEQ(e3, e2)) 156 | 157 | // Output: 158 | // LEQ(1, (2, 1, 1)) = true 159 | // LEQ(1, (1, 1, 1)) = true 160 | // LEQ(3, (2, 1, 1)) = false 161 | } 162 | 163 | func ExampleLeqLeftNode() { 164 | e1 := NewNode(two, one, one) 165 | e2 := NewLeaf(two) 166 | e3 := NewNode(two, one, one) 167 | 168 | fmt.Printf("LEQ(%s, %s) = %t\n", e1, e2, LEQ(e1, e2)) 169 | fmt.Printf("LEQ(%s, %s) = %t\n", e1, e3, LEQ(e1, e3)) 170 | 171 | // Output: 172 | // LEQ((2, 1, 1), 2) = false 173 | // LEQ((2, 1, 1), (2, 1, 1)) = true 174 | } 175 | 176 | func ExampleBitPack_EncodeEvent_Leaves() { 177 | source0 := NewLeaf(one) 178 | source1 := NewLeaf(uint32(4)) 179 | source2 := NewLeaf(uint32(8)) 180 | source3 := NewLeaf(uint32(13)) 181 | pack0 := bit.NewPack() 182 | pack1 := bit.NewPack() 183 | pack2 := bit.NewPack() 184 | pack3 := bit.NewPack() 185 | source0.Pack(pack0) 186 | source1.Pack(pack1) 187 | source2.Pack(pack2) 188 | source3.Pack(pack3) 189 | fmt.Printf("enc(%2s, 2) = %s\n", source0, pack0) 190 | fmt.Printf("enc(%2s, 2) = %s\n", source1, pack1) 191 | fmt.Printf("enc(%2s, 2) = %s\n", source2, pack2) 192 | fmt.Printf("enc(%2s, 2) = %s\n", source3, pack3) 193 | // Output: 194 | // enc( 1, 2) = <<1:1, 0:1, 1:2>> 195 | // enc( 4, 2) = <<1:1, 1:1, 0:1, 0:3>> 196 | // enc( 8, 2) = <<1:1, 1:1, 0:1, 4:3>> 197 | // enc(13, 2) = <<1:1, 1:1, 1:1, 0:1, 1:4>> 198 | } 199 | 200 | func ExampleBitPack_EncodeEvent_Nodes() { 201 | source0 := NewNode(zero, zero, one) 202 | source1 := NewNode(zero, one, zero) 203 | source2 := NewNode(zero, one, one) 204 | source3 := NewNode(one, zero, one) 205 | source4 := NewNode(one, one, zero) 206 | source5 := NewNode(one, one, one) 207 | pack0 := bit.NewPack() 208 | pack1 := bit.NewPack() 209 | pack2 := bit.NewPack() 210 | pack3 := bit.NewPack() 211 | pack4 := bit.NewPack() 212 | pack5 := bit.NewPack() 213 | source0.Pack(pack0) 214 | source1.Pack(pack1) 215 | source2.Pack(pack2) 216 | source3.Pack(pack3) 217 | source4.Pack(pack4) 218 | source5.Pack(pack5) 219 | 220 | fmt.Printf("enc(%2s) = %s\n", source0, pack0) 221 | fmt.Printf("enc(%2s) = %s\n", source1, pack1) 222 | fmt.Printf("enc(%2s) = %s\n", source2, pack2) 223 | fmt.Printf("enc(%2s) = %s\n", source3, pack3) 224 | fmt.Printf("enc(%2s) = %s\n", source4, pack4) 225 | fmt.Printf("enc(%2s) = %s\n", source5, pack5) 226 | 227 | // Output: 228 | // enc((0, 0, 1)) = <<0:1, 0:2, 1:1, 0:1, 1:2>> 229 | // enc((0, 1, 0)) = <<0:1, 1:2, 1:1, 0:1, 1:2>> 230 | // enc((0, 1, 1)) = <<0:1, 2:2, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>> 231 | // enc((1, 0, 1)) = <<0:1, 3:2, 0:1, 0:1, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>> 232 | // enc((1, 1, 0)) = <<0:1, 3:2, 0:1, 1:1, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>> 233 | // enc((1, 1, 1)) = <<0:1, 3:2, 1:1, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>> 234 | } 235 | 236 | func ExampleBitUnPack_decodeEvent_Leaves() { 237 | packer := bit.NewPack() 238 | NewLeaf(zero).Pack(packer) 239 | unpacker := bit.NewUnPack(packer.Pack()) 240 | event0 := UnPack(unpacker) 241 | fmt.Printf("dec(%s) = %s\n", packer, event0) 242 | 243 | packer = bit.NewPack() 244 | NewLeaf(one).Pack(packer) 245 | unpacker = bit.NewUnPack(packer.Pack()) 246 | event0 = UnPack(unpacker) 247 | fmt.Printf("dec(%s) = %s\n", packer, event0) 248 | 249 | packer = bit.NewPack() 250 | NewLeaf(uint32(13)).Pack(packer) 251 | unpacker = bit.NewUnPack(packer.Pack()) 252 | event0 = UnPack(unpacker) 253 | fmt.Printf("dec(%s) = %s\n", packer, event0) 254 | 255 | // Output: 256 | // dec(<<1:1, 0:1, 0:2>>) = 0 257 | // dec(<<1:1, 0:1, 1:2>>) = 1 258 | // dec(<<1:1, 1:1, 1:1, 0:1, 1:4>>) = 13 259 | } 260 | 261 | func ExampleBitUnPack_decodeEvent_Nodes() { 262 | packer := bit.NewPack() 263 | NewNode(zero, zero, one).Pack(packer) 264 | unpacker := bit.NewUnPack(packer.Pack()) 265 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 266 | 267 | packer = bit.NewPack() 268 | NewNode(zero, one, zero).Pack(packer) 269 | unpacker = bit.NewUnPack(packer.Pack()) 270 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 271 | 272 | packer = bit.NewPack() 273 | NewNode(zero, one, one).Pack(packer) 274 | unpacker = bit.NewUnPack(packer.Pack()) 275 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 276 | 277 | packer = bit.NewPack() 278 | NewNode(one, zero, one).Pack(packer) 279 | unpacker = bit.NewUnPack(packer.Pack()) 280 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 281 | 282 | packer = bit.NewPack() 283 | NewNode(one, one, zero).Pack(packer) 284 | unpacker = bit.NewUnPack(packer.Pack()) 285 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 286 | 287 | packer = bit.NewPack() 288 | NewNode(one, one, one).Pack(packer) 289 | unpacker = bit.NewUnPack(packer.Pack()) 290 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 291 | 292 | // Output: 293 | // dec(<<0:1, 0:2, 1:1, 0:1, 1:2>>) = (0, 0, 1) 294 | // dec(<<0:1, 1:2, 1:1, 0:1, 1:2>>) = (0, 1, 0) 295 | // dec(<<0:1, 2:2, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>>) = (0, 1, 1) 296 | // dec(<<0:1, 3:2, 0:1, 0:1, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>>) = (1, 0, 1) 297 | // dec(<<0:1, 3:2, 0:1, 1:1, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>>) = (1, 1, 0) 298 | // dec(<<0:1, 3:2, 1:1, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2, 1:1, 0:1, 1:2>>) = (1, 1, 1) 299 | } 300 | -------------------------------------------------------------------------------- /id/id.go: -------------------------------------------------------------------------------- 1 | package id 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fgrid/itc/bit" 6 | "log" 7 | ) 8 | 9 | type ID struct { 10 | Value uint32 11 | Left, Right *ID 12 | IsLeaf bool 13 | } 14 | 15 | const ( 16 | zero = uint32(0) 17 | one = uint32(1) 18 | two = uint32(2) 19 | three = uint32(3) 20 | ) 21 | 22 | func New() *ID { 23 | return NewWithValue(one) 24 | } 25 | 26 | func NewWithValue(value uint32) *ID { 27 | return &ID{Value: value, IsLeaf: true} 28 | } 29 | 30 | func (i *ID) asLeaf(value uint32) *ID { 31 | i.Value, i.IsLeaf, i.Left, i.Right = value, true, nil, nil 32 | return i 33 | } 34 | 35 | func (i *ID) asNode(left, right uint32) *ID { 36 | return i.asNodeWithIds(NewWithValue(left), NewWithValue(right)) 37 | } 38 | 39 | func (i *ID) asNodeWithIds(left, right *ID) *ID { 40 | i.Value, i.IsLeaf, i.Left, i.Right = 0, false, left, right 41 | return i 42 | } 43 | 44 | // Normalize an ID as defined in section "5.2 Normal form" 45 | func (i *ID) Norm() *ID { 46 | if i.IsLeaf || !i.Left.IsLeaf || !i.Right.IsLeaf || i.Left.Value != i.Right.Value { 47 | return i 48 | } 49 | return i.asLeaf(i.Left.Value) 50 | } 51 | 52 | // Split an ID as defined in section "5.3.2 Fork" 53 | func (i *ID) Split() (i1, i2 *ID) { 54 | 55 | i1 = New() 56 | i2 = New() 57 | 58 | if i.IsLeaf && i.Value == 0 { 59 | // split(0) = (0, 0) 60 | i1.Value = 0 61 | i2.Value = 0 62 | return 63 | } 64 | if i.IsLeaf && i.Value == 1 { 65 | // split(1) = ((1,0), (0,1)) 66 | i1.asNode(one, zero) 67 | i2.asNode(zero, one) 68 | return 69 | } 70 | if (i.Left.IsLeaf && i.Left.Value == 0) && (!i.Right.IsLeaf || i.Right.Value == 1) { 71 | // split((0, i)) = ((0, i1), (0, i2)), where (i1, i2) = split(i) 72 | r1, r2 := i.Right.Split() 73 | i1.asNodeWithIds(NewWithValue(zero), r1) 74 | i2.asNodeWithIds(NewWithValue(zero), r2) 75 | return 76 | } 77 | if (!i.Left.IsLeaf || i.Left.Value == 1) && (i.Right.IsLeaf && i.Right.Value == 0) { 78 | // split((i, 0)) = ((i1, 0), (i2, 0)), where (i1, i2) = split(i) 79 | l1, l2 := i.Left.Split() 80 | i1.asNodeWithIds(l1, NewWithValue(zero)) 81 | i2.asNodeWithIds(l2, NewWithValue(zero)) 82 | return 83 | } 84 | if (!i.Left.IsLeaf || i.Left.Value == 1) && (!i.Right.IsLeaf || i.Right.Value == 1) { 85 | // split((i1, i2)) = ((i1, 0), (0, i2)) 86 | i1.asNodeWithIds(i.Left, NewWithValue(zero)) 87 | i2.asNodeWithIds(NewWithValue(zero), i.Right) 88 | return 89 | } 90 | log.Fatalf("unable to split ID with unexpected setup: %s", i.String()) 91 | return 92 | } 93 | 94 | func (i *ID) String() string { 95 | if i.IsLeaf { 96 | return fmt.Sprintf("%d", i.Value) 97 | } 98 | return fmt.Sprintf("(%s, %s)", i.Left, i.Right) 99 | } 100 | 101 | func (i *ID) Sum(i1, i2 *ID) *ID { 102 | if i1.IsLeaf && i1.Value == 0 { 103 | i.Value = i2.Value 104 | i.Left, i.Right = i2.Left, i2.Right 105 | i.IsLeaf = i2.IsLeaf 106 | return i 107 | } 108 | if i2.IsLeaf && i2.Value == 0 { 109 | i.Value = i1.Value 110 | i.Left, i.Right = i1.Left, i1.Right 111 | i.IsLeaf = i1.IsLeaf 112 | return i 113 | } 114 | return i.asNodeWithIds(New().Sum(i1.Left, i2.Left), New().Sum(i1.Right, i2.Right)).Norm() 115 | } 116 | 117 | func (i *ID) Pack(p *bit.Pack) { 118 | if i.IsLeaf { 119 | p.Push(zero, two) 120 | p.Push(i.Value, one) 121 | return 122 | } 123 | if i.Left.IsLeaf && i.Left.Value == 0 { 124 | p.Push(one, two) 125 | i.Right.Pack(p) 126 | return 127 | } 128 | if i.Right.IsLeaf && i.Right.Value == 0 { 129 | p.Push(two, two) 130 | i.Left.Pack(p) 131 | return 132 | } 133 | p.Push(three, two) 134 | i.Left.Pack(p) 135 | i.Right.Pack(p) 136 | return 137 | } 138 | 139 | func UnPack(bup *bit.UnPack) *ID { 140 | i := New() 141 | switch bup.Pop(two) { 142 | case 0: 143 | i.asLeaf(bup.Pop(one)) 144 | case 1: 145 | newID := UnPack(bup) 146 | i.asNodeWithIds(NewWithValue(zero), newID) 147 | case 2: 148 | newID := UnPack(bup) 149 | i.asNodeWithIds(newID, NewWithValue(zero)) 150 | case 3: 151 | newLeft := UnPack(bup) 152 | newRight := UnPack(bup) 153 | i.asNodeWithIds(newLeft, newRight) 154 | } 155 | return i 156 | } 157 | -------------------------------------------------------------------------------- /id/id_test.go: -------------------------------------------------------------------------------- 1 | package id 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fgrid/itc/bit" 6 | "testing" 7 | ) 8 | 9 | func TestIdAsLeaf(t *testing.T) { 10 | i := New() 11 | i.asLeaf(zero) 12 | if !i.IsLeaf { 13 | t.Error("id is not recognized as leaf after \"asLeaf()\"") 14 | } 15 | if i.Left != nil || i.Right != nil { 16 | t.Error("Left or Right is filled - should not in a leaf") 17 | } 18 | } 19 | 20 | func TestIdLeafStringer(t *testing.T) { 21 | idString := New().asLeaf(one).String() 22 | if idString != "1" { 23 | t.Errorf("leaf id did not serialize as expected %q", idString) 24 | } 25 | } 26 | 27 | func TestIdNodeStringer(t *testing.T) { 28 | id := New().asNode(one, two) 29 | idString := id.String() 30 | if idString != "(1, 2)" { 31 | t.Errorf("node id did not serialize as expected %q", idString) 32 | } 33 | } 34 | 35 | func ExampleSplitId0() { 36 | source := NewWithValue(zero) 37 | i1, i2 := source.Split() 38 | 39 | fmt.Printf("split(%s) = (%s, %s)\n", source, i1, i2) 40 | // Output: 41 | // split(0) = (0, 0) 42 | } 43 | 44 | func ExampleSplitId1() { 45 | source := NewWithValue(one) 46 | i1, i2 := source.Split() 47 | 48 | fmt.Printf("split(%s) = (%s, %s)\n", source, i1, i2) 49 | // Output: 50 | // split(1) = ((1, 0), (0, 1)) 51 | } 52 | 53 | func ExampleSplitIdLeafNode() { 54 | source := New().asNode(zero, one) 55 | i1, i2 := source.Split() 56 | 57 | fmt.Printf("split(%s) = (%s, %s)\n", source, i1, i2) 58 | // Output: 59 | // split((0, 1)) = ((0, (1, 0)), (0, (0, 1))) 60 | } 61 | 62 | func ExampleSplitIdNodeLeaf() { 63 | source := New().asNode(one, zero) 64 | i1, i2 := source.Split() 65 | 66 | fmt.Printf("split(%s) = (%s, %s)\n", source, i1, i2) 67 | // Output: 68 | // split((1, 0)) = (((1, 0), 0), ((0, 1), 0)) 69 | } 70 | 71 | func ExampleSplitIdNodeNode() { 72 | source := New().asNode(one, one) 73 | i1, i2 := source.Split() 74 | 75 | fmt.Printf("split(%s) = (%s, %s)\n", source, i1, i2) 76 | // Output: 77 | // split((1, 1)) = ((1, 0), (0, 1)) 78 | } 79 | 80 | func ExampleNormalizeIdZero() { 81 | source := New().asNode(zero, zero) 82 | sourceString := source.String() 83 | fmt.Printf("norm(%s) = %s\n", sourceString, source.Norm()) 84 | // Output: 85 | // norm((0, 0)) = 0 86 | } 87 | 88 | func ExampleNormalizeIdOne() { 89 | source := New().asNode(one, one) 90 | sourceString := source.String() 91 | fmt.Printf("norm(%s) = %s\n", sourceString, source.Norm()) 92 | // Output: 93 | // norm((1, 1)) = 1 94 | } 95 | 96 | func ExampleSumIdLeaf() { 97 | i1 := NewWithValue(zero) 98 | i2 := NewWithValue(one) 99 | fmt.Printf("sum(%s, %s) = %s\n", i1, i2, New().Sum(i1, i2)) 100 | fmt.Printf("sum(%s, %s) = %s\n", i2, i1, New().Sum(i2, i1)) 101 | // Output: 102 | // sum(0, 1) = 1 103 | // sum(1, 0) = 1 104 | } 105 | 106 | func ExampleSumIdNode() { 107 | i1, i2 := New().Split() 108 | fmt.Printf("sum(%s, %s) = %s\n", i1, i2, New().Sum(i1, i2)) 109 | // Output: 110 | // sum((1, 0), (0, 1)) = 1 111 | } 112 | 113 | func ExampleBitPack_EncodeId_Leaves() { 114 | source0 := New().asLeaf(zero) 115 | source1 := New().asLeaf(one) 116 | pack0 := bit.NewPack() 117 | pack1 := bit.NewPack() 118 | source0.Pack(pack0) 119 | source1.Pack(pack1) 120 | fmt.Printf("enc(%s) = %s\n", source0, pack0) 121 | fmt.Printf("enc(%s) = %s\n", source1, pack1) 122 | // Output: 123 | // enc(0) = <<0:2, 0:1>> 124 | // enc(1) = <<0:2, 1:1>> 125 | } 126 | 127 | func ExampleBitPack_EnocdeId_Nodes() { 128 | sourceL := New().asNode(zero, one) 129 | sourceR := New().asNode(one, zero) 130 | sourceB := New().asNode(one, one) 131 | packL := bit.NewPack() 132 | packR := bit.NewPack() 133 | packB := bit.NewPack() 134 | sourceL.Pack(packL) 135 | sourceR.Pack(packR) 136 | sourceB.Pack(packB) 137 | fmt.Printf("enc(%s) = %s\n", sourceL, packL) 138 | fmt.Printf("enc(%s) = %s\n", sourceR, packR) 139 | fmt.Printf("enc(%s) = %s\n", sourceB, packB) 140 | // Output: 141 | // enc((0, 1)) = <<1:2, 0:2, 1:1>> 142 | // enc((1, 0)) = <<2:2, 0:2, 1:1>> 143 | // enc((1, 1)) = <<3:2, 0:2, 1:1, 0:2, 1:1>> 144 | } 145 | 146 | func ExampleBitUnPack_decodeID_Leaves() { 147 | packer := bit.NewPack() 148 | New().asLeaf(zero).Pack(packer) 149 | unpacker := bit.NewUnPack(packer.Pack()) 150 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 151 | 152 | packer = bit.NewPack() 153 | New().asLeaf(one).Pack(packer) 154 | unpacker = bit.NewUnPack(packer.Pack()) 155 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 156 | 157 | // Output: 158 | // dec(<<0:2, 0:1>>) = 0 159 | // dec(<<0:2, 1:1>>) = 1 160 | } 161 | 162 | func ExampleEncDecIdNode() { 163 | packer := bit.NewPack() 164 | New().asNode(zero, one).Pack(packer) 165 | unpacker := bit.NewUnPack(packer.Pack()) 166 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 167 | 168 | packer = bit.NewPack() 169 | New().asNode(one, zero).Pack(packer) 170 | unpacker = bit.NewUnPack(packer.Pack()) 171 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 172 | 173 | packer = bit.NewPack() 174 | New().asNode(one, one).Pack(packer) 175 | unpacker = bit.NewUnPack(packer.Pack()) 176 | fmt.Printf("dec(%s) = %s\n", packer, UnPack(unpacker)) 177 | 178 | // Output: 179 | // dec(<<1:2, 0:2, 1:1>>) = (0, 1) 180 | // dec(<<2:2, 0:2, 1:1>>) = (1, 0) 181 | // dec(<<3:2, 0:2, 1:1, 0:2, 1:1>>) = (1, 1) 182 | } 183 | -------------------------------------------------------------------------------- /stamp.go: -------------------------------------------------------------------------------- 1 | // Package itc implements the interval tree clock as described in the paper 2 | // 'Interval Tree Clocks: A Logical Clock for Dynamic Systems' by Paulo Sergio Almeida, 3 | // Carlos Baquero and Victor Fonte. (http://gsd.di.uminho.pt/members/cbm/ps/itc2008.pdf) 4 | // 5 | // Causality tracking mechanisms can be modeled by a set of core operations: fork; event and join, that 6 | // act on stamps (logical clocks) whose structure is a pair (i, e), formed by an id and an event component 7 | // that encodes causally known events. 8 | package itc 9 | 10 | import ( 11 | "fmt" 12 | "github.com/fgrid/itc/bit" 13 | "github.com/fgrid/itc/event" 14 | "github.com/fgrid/itc/id" 15 | ) 16 | 17 | // Stamp declares the state of the clock for a given identity and a given stream of events. 18 | type Stamp struct { 19 | event *event.Event 20 | id *id.ID 21 | } 22 | 23 | // NewStamp creates a new so called seed-Stamp (represented as: (1, 0)). 24 | func NewStamp() *Stamp { 25 | return &Stamp{event: event.New(), id: id.New()} 26 | } 27 | 28 | // Event adds a new event to the clock's event component, so that if (i, e') results from event((i, e)) 29 | // the causal ordering is such that e < e'. 30 | func (s *Stamp) Event() { 31 | oldE := s.event.Clone() 32 | newE := s.fill() 33 | if newE.Equals(oldE) { 34 | s.event, _ = s.grow() 35 | } else { 36 | s.event = newE 37 | } 38 | } 39 | 40 | func (s *Stamp) fill() *event.Event { 41 | return fill(s.id, s.event) 42 | } 43 | 44 | // Fork clones the causal past of a stamp, resulting in a pair of stamps that 45 | // have identical copies of the event component and distinct IDs. 46 | func (s *Stamp) Fork() *Stamp { 47 | st := NewStamp() 48 | id1, id2 := s.id.Split() 49 | s.id = id1 50 | st.id = id2 51 | st.event = s.event.Clone() 52 | return st 53 | } 54 | 55 | func (s *Stamp) grow() (*event.Event, int) { 56 | return grow(s.id, s.event) 57 | } 58 | 59 | // Join merges two stamps, producing a new one. 60 | func (s *Stamp) Join(other *Stamp) { 61 | s.id = id.New().Sum(s.id, other.id) 62 | s.event = event.Join(s.event, other.event) 63 | } 64 | 65 | // LEQ Compares the stamp with the given other stamp and returns 'true' if this stamp is less or equal (LEQ). 66 | func (s *Stamp) LEQ(other *Stamp) bool { 67 | return event.LEQ(s.event, other.event) 68 | } 69 | 70 | // MarshalBinary encodes the stamp s into a binary form and returns the result. 71 | func (s *Stamp) MarshalBinary() ([]byte, error) { 72 | bp := bit.NewPack() 73 | s.Pack(bp) 74 | return bp.Pack(), nil 75 | } 76 | 77 | // String returns the string corresponding to stamp s. 78 | func (s *Stamp) String() string { 79 | return fmt.Sprintf("(%s, %s)", s.id, s.event) 80 | } 81 | 82 | // UnmarshalBinary decodes the stamp s from the given binary form data (created by MarshalBinary). 83 | func (s *Stamp) UnmarshalBinary(data []byte) error { 84 | bup := bit.NewUnPack(data) 85 | s.UnPack(bup) 86 | return nil 87 | } 88 | 89 | func fill(i *id.ID, e *event.Event) *event.Event { 90 | if i.IsLeaf { 91 | if i.Value == 0 { 92 | return e 93 | } 94 | return event.NewLeaf(e.Max()) 95 | } 96 | if e.IsLeaf { 97 | return e 98 | } 99 | r := event.NewEmptyNode(e.Value) 100 | if i.Left.IsLeaf && i.Left.Value == 1 { 101 | r.Right = fill(i.Right, e.Right) 102 | r.Left = event.NewLeaf(event.Max(e.Left.Max(), r.Right.Min())) 103 | } else if i.Right.IsLeaf && i.Right.Value == 1 { 104 | r.Left = fill(i.Left, e.Left) 105 | r.Right = event.NewLeaf(event.Max(e.Right.Max(), r.Left.Min())) 106 | } else { 107 | r.Left = fill(i.Left, e.Left) 108 | r.Right = fill(i.Right, e.Right) 109 | } 110 | return r.Norm() 111 | } 112 | 113 | func grow(i *id.ID, e *event.Event) (*event.Event, int) { 114 | if e.IsLeaf { 115 | if i.IsLeaf && i.Value == 1 { 116 | return event.NewLeaf(e.Value + 1), 0 117 | } 118 | ex, c := grow(i, event.NewEmptyNode(e.Value)) 119 | return ex, c + 99999 120 | } 121 | if i.Left.IsLeaf && i.Left.Value == 0 { 122 | exr, cr := grow(i.Right, e.Right) 123 | r := event.NewEmptyNode(e.Value) 124 | r.Left = e.Left 125 | r.Right = exr 126 | return r, cr + 1 127 | } 128 | if i.Right.IsLeaf && i.Right.Value == 0 { 129 | exl, cl := grow(i.Left, e.Left) 130 | r := event.NewEmptyNode(e.Value) 131 | r.Left = exl 132 | r.Right = e.Right 133 | return r, cl + 1 134 | } 135 | exl, cl := grow(i.Left, e.Left) 136 | exr, cr := grow(i.Right, e.Right) 137 | if cl < cr { 138 | r := event.NewEmptyNode(e.Value) 139 | r.Left = exl 140 | r.Right = e.Right 141 | return r, cl + 1 142 | } 143 | r := event.NewEmptyNode(e.Value) 144 | r.Left = e.Left 145 | r.Right = exr 146 | return r, cr + 1 147 | } 148 | 149 | func (s *Stamp) Pack(p *bit.Pack) { 150 | s.id.Pack(p) 151 | s.event.Pack(p) 152 | } 153 | 154 | func (s *Stamp) UnPack(bup *bit.UnPack) { 155 | s.id = id.UnPack(bup) 156 | s.event = event.UnPack(bup) 157 | } 158 | -------------------------------------------------------------------------------- /stamp_test.go: -------------------------------------------------------------------------------- 1 | package itc 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func Example1() { 9 | a := NewStamp() 10 | fmt.Printf("stage 1: a := NewStamp()\n") 11 | fmt.Printf("a: %s\n", a) 12 | // Output: 13 | // stage 1: a := NewStamp() 14 | // a: (1, 0) 15 | } 16 | 17 | func Example2() { 18 | a := NewStamp() 19 | b := a.Fork() 20 | fmt.Printf("stage 2: b := a.Fork()\n") 21 | fmt.Printf("a: %s\n", a) 22 | fmt.Printf("b: %s\n", b) 23 | 24 | // Output: 25 | // stage 2: b := a.Fork() 26 | // a: ((1, 0), 0) 27 | // b: ((0, 1), 0) 28 | } 29 | 30 | func Example3() { 31 | a := NewStamp() 32 | b := a.Fork() 33 | a.Event() 34 | b.Event() 35 | fmt.Printf("stage 3: a.Event(), b.Event()\n") 36 | fmt.Printf("a: %s\n", a) 37 | fmt.Printf("b: %s\n", b) 38 | 39 | // Output: 40 | // stage 3: a.Event(), b.Event() 41 | // a: ((1, 0), (0, 1, 0)) 42 | // b: ((0, 1), (0, 0, 1)) 43 | } 44 | 45 | func Example4() { 46 | a := NewStamp() 47 | b := a.Fork() 48 | a.Event() 49 | b.Event() 50 | c := a.Fork() 51 | b.Event() 52 | fmt.Printf("stage 4: c := a.Fork(), b.Event()\n") 53 | fmt.Printf("a: %s\n", a) 54 | fmt.Printf("b: %s\n", b) 55 | fmt.Printf("c: %s\n", c) 56 | 57 | // Output: 58 | // stage 4: c := a.Fork(), b.Event() 59 | // a: (((1, 0), 0), (0, 1, 0)) 60 | // b: ((0, 1), (0, 0, 2)) 61 | // c: (((0, 1), 0), (0, 1, 0)) 62 | } 63 | 64 | func Example5() { 65 | a := NewStamp() // 1 66 | b := a.Fork() // 2 67 | a.Event() // 3 68 | b.Event() // 3 69 | c := a.Fork() // 4 70 | b.Event() // 4 71 | a.Event() // 5 72 | b.Join(c) // 5 73 | fmt.Printf("stage 5: a.Event(), b.Join(c)\n") 74 | fmt.Printf("a: %s\n", a) 75 | fmt.Printf("b: %s\n", b) 76 | 77 | // Output: 78 | // stage 5: a.Event(), b.Join(c) 79 | // a: (((1, 0), 0), (0, (1, 1, 0), 0)) 80 | // b: (((0, 1), 1), (1, 0, 1)) 81 | } 82 | 83 | func Example6() { 84 | a := NewStamp() // 1 85 | b := a.Fork() // 2 86 | a.Event() // 3 87 | b.Event() // 3 88 | c := a.Fork() // 4 89 | b.Event() // 4 90 | a.Event() // 5 91 | b.Join(c) // 5 92 | c = b.Fork() // 6 93 | 94 | fmt.Printf("stage 6: c = b.Fork()\n") 95 | fmt.Printf("a: %s\n", a) 96 | fmt.Printf("b: %s\n", b) 97 | fmt.Printf("c: %s\n", c) 98 | 99 | // Output: 100 | // stage 6: c = b.Fork() 101 | // a: (((1, 0), 0), (0, (1, 1, 0), 0)) 102 | // b: (((0, 1), 0), (1, 0, 1)) 103 | // c: ((0, 1), (1, 0, 1)) 104 | } 105 | 106 | func Example7() { 107 | a := NewStamp() // 1 108 | b := a.Fork() // 2 109 | a.Event() // 3 110 | b.Event() // 3 111 | c := a.Fork() // 4 112 | b.Event() // 4 113 | a.Event() // 5 114 | b.Join(c) // 5 115 | c = b.Fork() // 6 116 | a.Join(b) // 7 117 | 118 | fmt.Printf("stage 7: a.Join(b)\n") 119 | fmt.Printf("a: %s\n", a) 120 | fmt.Printf("c: %s\n", c) 121 | 122 | // Output: 123 | // stage 7: a.Join(b) 124 | // a: ((1, 0), (1, (0, 1, 0), 1)) 125 | // c: ((0, 1), (1, 0, 1)) 126 | } 127 | 128 | func Example8() { 129 | a := NewStamp() // 1 130 | b := a.Fork() // 2 131 | a.Event() // 3 132 | b.Event() // 3 133 | c := a.Fork() // 4 134 | b.Event() // 4 135 | a.Event() // 5 136 | b.Join(c) // 5 137 | c = b.Fork() // 6 138 | a.Join(b) // 7 139 | a.Event() // 8 140 | 141 | fmt.Printf("stage 8: a.Event()\n") 142 | fmt.Printf("a: %s\n", a) 143 | fmt.Printf("c: %s\n", c) 144 | 145 | // Output: 146 | // stage 8: a.Event() 147 | // a: ((1, 0), 2) 148 | // c: ((0, 1), (1, 0, 1)) 149 | } 150 | 151 | func TestStampEmptyStringer(t *testing.T) { 152 | stampString := NewStamp().String() 153 | if stampString != "(1, 0)" { 154 | t.Errorf("stamp did not serialize as expected %q", stampString) 155 | } 156 | } 157 | 158 | func ExampleStamp_MarshalBinary_seed() { 159 | seed := NewStamp() 160 | seedData, _ := seed.MarshalBinary() 161 | fmt.Printf("%s = % x\n", seed, seedData) 162 | // Output: 163 | // (1, 0) = 30 00 00 00 164 | } 165 | 166 | func ExampleStamp_MarshalBinary_seedAfterFork() { 167 | seed := NewStamp() 168 | seed.Fork() 169 | seedData, _ := seed.MarshalBinary() 170 | fmt.Printf("%s = % x\n", seed, seedData) 171 | // Output: 172 | // ((1, 0), 0) = 8c 00 00 00 173 | } 174 | 175 | func ExampleStamp_UnmarshalBinary() { 176 | data := []byte{0x8c, 00, 00, 00} 177 | stamp := NewStamp() 178 | stamp.UnmarshalBinary(data) 179 | fmt.Printf("% x = %s\n", data, stamp) 180 | // Output: 181 | // 8c 00 00 00 = ((1, 0), 0) 182 | } 183 | --------------------------------------------------------------------------------