Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Monomorphize treelist.go
Browse files Browse the repository at this point in the history
  • Loading branch information
Storyyeller committed Sep 25, 2016
1 parent 7ad8903 commit 55e8e65
Show file tree
Hide file tree
Showing 5 changed files with 419 additions and 42 deletions.
125 changes: 125 additions & 0 deletions go/src/enjarify-go/jvm/treelist.go_
Original file line number Diff line number Diff line change
@@ -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}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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}
}
125 changes: 125 additions & 0 deletions go/src/enjarify-go/jvm/treelist_bool.go
Original file line number Diff line number Diff line change
@@ -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ᐸboolᐳ struct {
missing bool
direct [16]bool
children [16]*ImmutableTreeListᐸboolᐳ
}

func newTreeListᐸboolᐳ(missing bool) *ImmutableTreeListᐸboolᐳ {
self := ImmutableTreeListᐸboolᐳ{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}
}
Loading

0 comments on commit 55e8e65

Please sign in to comment.