summaryrefslogtreecommitdiff
path: root/vendor/github.com/dalzilio/rudd/replace.go
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-22 17:35:49 -0600
committermo khan <mo@mokhan.ca>2025-07-22 17:35:49 -0600
commit20ef0d92694465ac86b550df139e8366a0a2b4fa (patch)
tree3f14589e1ce6eb9306a3af31c3a1f9e1af5ed637 /vendor/github.com/dalzilio/rudd/replace.go
parent44e0d272c040cdc53a98b9f1dc58ae7da67752e6 (diff)
feat: connect to spicedb
Diffstat (limited to 'vendor/github.com/dalzilio/rudd/replace.go')
-rw-r--r--vendor/github.com/dalzilio/rudd/replace.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/vendor/github.com/dalzilio/rudd/replace.go b/vendor/github.com/dalzilio/rudd/replace.go
new file mode 100644
index 0000000..6a33658
--- /dev/null
+++ b/vendor/github.com/dalzilio/rudd/replace.go
@@ -0,0 +1,98 @@
+// Copyright (c) 2021 Silvano DAL ZILIO
+//
+// MIT License
+
+package rudd
+
+import (
+ "fmt"
+ "math"
+)
+
+var _REPLACEID = 1
+
+// Replacer is the types of substitution objects used in a Replace operation,
+// that substitutes variables in a BDD "function". The only method returning an
+// object of this type is the NewReplacer method. The result obtained when using
+// a replacer created from a BDD, in a Replace operation over a different BDD is
+// unspecified.
+type Replacer interface {
+ Replace(int32) (int32, bool)
+ Id() int
+}
+
+type replacer struct {
+ id int // unique identifier used for caching intermediate results
+ image []int32 // map the level of old variables to the level of new variables
+ last int32 // last index in the Replacer, to speed up computations
+}
+
+func (r *replacer) String() string {
+ res := fmt.Sprintf("replacer(last: %d)[", r.last)
+ first := true
+ for k, v := range r.image {
+ if k != int(v) {
+ if !first {
+ res += ", "
+ }
+ first = false
+ res += fmt.Sprintf("%d<-%d", k, v)
+ }
+ }
+ return res + "]"
+}
+
+func (r *replacer) Replace(level int32) (int32, bool) {
+ if level > r.last {
+ return level, false
+ }
+ return r.image[level], true
+}
+
+func (r *replacer) Id() int {
+ return r.id
+}
+
+// NewReplacer returns a Replacer that can be used for substituting variable
+// oldvars[k] with newvars[k] in the BDD b. We return an error if the two slices
+// do not have the same length or if we find the same index twice in either of
+// them. All values must be in the interval [0..Varnum).
+func (b *BDD) NewReplacer(oldvars, newvars []int) (Replacer, error) {
+ res := &replacer{}
+ if len(oldvars) != len(newvars) {
+ return nil, fmt.Errorf("unmatched length of slices")
+ }
+ if _REPLACEID == (math.MaxInt32 >> 2) {
+ return nil, fmt.Errorf("too many replacers created")
+ }
+ res.id = (_REPLACEID << 2) | cacheidREPLACE
+ _REPLACEID++
+ varnum := b.Varnum()
+ support := make([]bool, varnum)
+ res.image = make([]int32, varnum)
+ for k := range res.image {
+ res.image[k] = int32(k)
+ }
+ for k, v := range oldvars {
+ if support[v] {
+ return nil, fmt.Errorf("duplicate variable (%d) in oldvars", v)
+ }
+ if v >= varnum {
+ return nil, fmt.Errorf("invalid variable in oldvars (%d)", v)
+ }
+ if newvars[k] >= varnum {
+ return nil, fmt.Errorf("invalid variable in newvars (%d)", v)
+ }
+ support[v] = true
+ res.image[v] = int32(newvars[k])
+ if int32(v) > res.last {
+ res.last = int32(v)
+ }
+ }
+ for _, v := range newvars {
+ if int(res.image[v]) != v {
+ return nil, fmt.Errorf("variable in newvars (%d) also occur in oldvars", v)
+ }
+ }
+ return res, nil
+}