Permalink
Browse files

Monomorphize treelist.go

  • Loading branch information...
Storyyeller committed Sep 25, 2016
1 parent 7ad8903 commit 55e8e65e681b15f026625c38024a63adab8cd446
@@ -0,0 +1,125 @@
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jvm
// This class represents a list as a persistent n-ary tree
// This has much slower access and updates than a real list but has the advantage
// of sharing memory with previous versions of the list when only a few elements
// are changed. See http://en.wikipedia.org/wiki/Persistent_data_structure//Trees
// Also, default values are not stored, so this is good for sparse arrays
type ImmutableTreeListᐸElementTᐳ struct {
missing ElementT
direct [16]ElementT
children [16]*ImmutableTreeListᐸElementTᐳ
}
func newTreeListᐸElementTᐳ(missing ElementT) *ImmutableTreeListᐸElementTᐳ {
self := ImmutableTreeListᐸElementTᐳ{missing: missing}
for i := 0; i < 16; i++ {
self.direct[i] = missing
}
// Subtrees allocated lazily
return &self
}
func (self *ImmutableTreeListᐸElementTᐳ) get(i uint16) ElementT {
if i < 16 {
return self.direct[i]
}
i -= 16
ci := i % 16
i = i / 16
child := self.children[ci]
if child == nil {
return self.missing
}
return child.get(i)
}
func (self *ImmutableTreeListᐸElementTᐳ) set(i uint16, val ElementT) *ImmutableTreeListᐸElementTᐳ {
if i < 16 {
if val == self.direct[i] {
return self
}
temp := self.direct
temp[i] = val
return &ImmutableTreeListᐸElementTᐳ{self.missing, temp, self.children}
}
i -= 16
ci := i % 16
i = i / 16
child := self.children[ci]
if child == nil {
if val == self.missing {
return self
}
child = newTreeListᐸElementTᐳ(self.missing).set(i, val)
} else {
if val == child.get(i) {
return self
}
child = child.set(i, val)
}
temp := self.children
temp[ci] = child
return &ImmutableTreeListᐸElementTᐳ{self.missing, self.direct, temp}
}
func (left *ImmutableTreeListᐸElementTᐳ) merge(right *ImmutableTreeListᐸElementTᐳ, f func(ElementT, ElementT) ElementT) *ImmutableTreeListᐸElementTᐳ {
// Effectively computes [func(x, y) for x, y in zip(left, right)]
// Assume func(x, x) == x
if left == right {
return left
}
if left == nil {
left, right = right, left
}
missing := left.missing
direct := [16]ElementT{}
children := [16]*ImmutableTreeListᐸElementTᐳ{}
if right == nil {
for i, x := range left.direct {
direct[i] = f(x, missing)
}
for i, child := range left.children {
children[i] = child.merge(nil, f)
}
} else {
for i, x := range left.direct {
direct[i] = f(x, right.direct[i])
}
for i, child := range left.children {
children[i] = child.merge(right.children[i], f)
}
if direct == right.direct && children == right.children {
return right
}
}
if direct == left.direct && children == left.children {
return left
}
return &ImmutableTreeListᐸElementTᐳ{missing, direct, children}
}
@@ -11,69 +11,66 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jvm
// The first SIZE elements are stored directly, the rest are stored in one of SPLIT subtrees
const SIZE = 16
const SPLIT = 16
package jvm
// This class represents a list as a persistent n-ary tree
// This has much slower access and updates than a real list but has the advantage
// of sharing memory with previous versions of the list when only a few elements
// are changed. See http://en.wikipedia.org/wiki/Persistent_data_structure//Trees
// Also, default values are not stored, so this is good for sparse arrays
type ImmutableTreeList struct {
missing interface{}
direct [SIZE]interface{}
children [SPLIT]*ImmutableTreeList
type ImmutableTreeListᐸArrayTᐳ struct {
missing ArrayT
direct [16]ArrayT
children [16]*ImmutableTreeListᐸArrayTᐳ
}
func newTreeList(missing interface{}) *ImmutableTreeList {
self := ImmutableTreeList{missing: missing}
for i := 0; i < SIZE; i++ {
func newTreeListᐸArrayTᐳ(missing ArrayT) *ImmutableTreeListᐸArrayTᐳ {
self := ImmutableTreeListᐸArrayTᐳ{missing: missing}
for i := 0; i < 16; i++ {
self.direct[i] = missing
}
// Subtrees allocated lazily
return &self
}
func (self *ImmutableTreeList) get(i uint16) interface{} {
if i < SIZE {
func (self *ImmutableTreeListᐸArrayTᐳ) get(i uint16) ArrayT {
if i < 16 {
return self.direct[i]
}
i -= SIZE
i -= 16
ci := i % SPLIT
i = i / SPLIT
ci := i % 16
i = i / 16
child := self.children[ci]
if child == nil {
return self.missing
}
return child.get(i)
}
func (self *ImmutableTreeList) set(i uint16, val interface{}) *ImmutableTreeList {
if i < SIZE {
func (self *ImmutableTreeListᐸArrayTᐳ) set(i uint16, val ArrayT) *ImmutableTreeListᐸArrayTᐳ {
if i < 16 {
if val == self.direct[i] {
return self
}
temp := self.direct
temp[i] = val
return &ImmutableTreeList{self.missing, temp, self.children}
return &ImmutableTreeListᐸArrayTᐳ{self.missing, temp, self.children}
}
i -= SIZE
i -= 16
ci := i % SPLIT
i = i / SPLIT
ci := i % 16
i = i / 16
child := self.children[ci]
if child == nil {
if val == self.missing {
return self
}
child = newTreeList(self.missing).set(i, val)
child = newTreeListᐸArrayTᐳ(self.missing).set(i, val)
} else {
if val == child.get(i) {
return self
@@ -83,10 +80,10 @@ func (self *ImmutableTreeList) set(i uint16, val interface{}) *ImmutableTreeList
temp := self.children
temp[ci] = child
return &ImmutableTreeList{self.missing, self.direct, temp}
return &ImmutableTreeListᐸArrayTᐳ{self.missing, self.direct, temp}
}
func (left *ImmutableTreeList) merge(right *ImmutableTreeList, f func(interface{}, interface{}) interface{}) *ImmutableTreeList {
func (left *ImmutableTreeListᐸArrayTᐳ) merge(right *ImmutableTreeListᐸArrayTᐳ, f func(ArrayT, ArrayT) ArrayT) *ImmutableTreeListᐸArrayTᐳ {
// Effectively computes [func(x, y) for x, y in zip(left, right)]
// Assume func(x, x) == x
if left == right {
@@ -98,8 +95,8 @@ func (left *ImmutableTreeList) merge(right *ImmutableTreeList, f func(interface{
}
missing := left.missing
direct := [SIZE]interface{}{}
children := [SPLIT]*ImmutableTreeList{}
direct := [16]ArrayT{}
children := [16]*ImmutableTreeListᐸArrayTᐳ{}
if right == nil {
for i, x := range left.direct {
@@ -124,5 +121,5 @@ func (left *ImmutableTreeList) merge(right *ImmutableTreeList, f func(interface{
if direct == left.direct && children == left.children {
return left
}
return &ImmutableTreeList{missing, direct, children}
return &ImmutableTreeListᐸArrayTᐳ{missing, direct, children}
}
@@ -0,0 +1,125 @@
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jvm
// This class represents a list as a persistent n-ary tree
// This has much slower access and updates than a real list but has the advantage
// of sharing memory with previous versions of the list when only a few elements
// are changed. See http://en.wikipedia.org/wiki/Persistent_data_structure//Trees
// Also, default values are not stored, so this is good for sparse arrays
type ImmutableTreeListboolstruct {
missing bool
direct [16]bool
children [16]*ImmutableTreeListᐸbool
}
func newTreeListᐸboolᐳ(missing bool) *ImmutableTreeListᐸboolᐳ {
self := ImmutableTreeListboolᐳ{missing: missing}
for i := 0; i < 16; i++ {
self.direct[i] = missing
}
// Subtrees allocated lazily
return &self
}
func (self *ImmutableTreeListᐸboolᐳ) get(i uint16) bool {
if i < 16 {
return self.direct[i]
}
i -= 16
ci := i % 16
i = i / 16
child := self.children[ci]
if child == nil {
return self.missing
}
return child.get(i)
}
func (self *ImmutableTreeListᐸboolᐳ) set(i uint16, val bool) *ImmutableTreeListᐸboolᐳ {
if i < 16 {
if val == self.direct[i] {
return self
}
temp := self.direct
temp[i] = val
return &ImmutableTreeListᐸboolᐳ{self.missing, temp, self.children}
}
i -= 16
ci := i % 16
i = i / 16
child := self.children[ci]
if child == nil {
if val == self.missing {
return self
}
child = newTreeListᐸboolᐳ(self.missing).set(i, val)
} else {
if val == child.get(i) {
return self
}
child = child.set(i, val)
}
temp := self.children
temp[ci] = child
return &ImmutableTreeListᐸboolᐳ{self.missing, self.direct, temp}
}
func (left *ImmutableTreeListᐸboolᐳ) merge(right *ImmutableTreeListᐸboolᐳ, f func(bool, bool) bool) *ImmutableTreeListᐸboolᐳ {
// Effectively computes [func(x, y) for x, y in zip(left, right)]
// Assume func(x, x) == x
if left == right {
return left
}
if left == nil {
left, right = right, left
}
missing := left.missing
direct := [16]bool{}
children := [16]*ImmutableTreeListᐸboolᐳ{}
if right == nil {
for i, x := range left.direct {
direct[i] = f(x, missing)
}
for i, child := range left.children {
children[i] = child.merge(nil, f)
}
} else {
for i, x := range left.direct {
direct[i] = f(x, right.direct[i])
}
for i, child := range left.children {
children[i] = child.merge(right.children[i], f)
}
if direct == right.direct && children == right.children {
return right
}
}
if direct == left.direct && children == left.children {
return left
}
return &ImmutableTreeListᐸboolᐳ{missing, direct, children}
}
Oops, something went wrong.

0 comments on commit 55e8e65

Please sign in to comment.